Feat: Add global Graphs

This commit is contained in:
Sallu9007
2025-04-27 18:57:12 +05:30
parent 0cf3c0e396
commit 75f40b7147
3 changed files with 289 additions and 10 deletions

View File

@@ -18,7 +18,8 @@ class AdminController extends Controller
// Admin dashboard (optional) // Admin dashboard (optional)
public function index() public function index()
{ {
return view('admin.dashboard'); $departments = Department::all();
return view('admin.dashboard', compact('departments'));
} }
// View responses submitted by users // View responses submitted by users
@@ -181,4 +182,86 @@ class AdminController extends Controller
'total' => $total, 'total' => $total,
]); ]);
} }
public function analyticsComparison(Request $request)
{
$departmentId = $request->query('department_id');
$models = [
'ActivitiesAttended' => ActivitiesAttended::class,
'ActivitiesOrganised' => ActivitiesOrganised::class,
'BooksPublished' => BooksPublished::class,
'ExternalEngagement' => ExternalEngagement::class,
'IvOrganised' => IvOrganised::class,
'OnlineCourse' => OnlineCourse::class,
'Patent' => Patent::class,
'Publication' => Publication::class,
];
$data = [];
foreach ($models as $label => $model) {
$count = $model::where('department_id', $departmentId)->count();
$data[] = [
'label' => $label,
'count' => $count,
];
$total = array_sum(array_column($data, 'count'));
}
return response()->json([
'labels' => array_column($data, 'label'),
'values' => array_column($data, 'count'),
'total' => $total
]);
}
public function analyticsContribution(Request $request)
{
$model = $request->query('model', 'all');
$models = [
'ActivitiesAttended' => ActivitiesAttended::class,
'ActivitiesOrganised' => ActivitiesOrganised::class,
'BooksPublished' => BooksPublished::class,
'ExternalEngagement' => ExternalEngagement::class,
'IvOrganised' => IvOrganised::class,
'OnlineCourse' => OnlineCourse::class,
'Patent' => Patent::class,
'Publication' => Publication::class,
];
$data = [];
if ($model === 'all') {
$departments = Department::all();
foreach ($departments as $department) {
$count = 0;
foreach ($models as $modelClass) {
$count += $modelClass::where('department_id', $department->id)->count();
}
$data[] = [
'label' => $department->name,
'count' => $count,
];
$total = array_sum(array_column($data, 'count'));
}
} else {
$modelClass = $models[$model];
$data = $modelClass::selectRaw('departments.name as label, COUNT(*) as count')
->join('departments', 'department_id', '=', 'departments.id')
->groupBy('departments.name')
->get()
->toArray();
$total = array_sum(array_column($data, 'count'));
}
return response()->json([
'labels' => array_column($data, 'label'),
'values' => array_column($data, 'count'),
'total' => $total
]);
}
} }

View File

@@ -18,39 +18,71 @@
<div class="mt-6"> <div class="mt-6">
<h3 class="text-lg font-semibold">Analytics</h3> <h3 class="text-lg font-semibold">Analytics</h3>
<div id="graphs-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-4"> <div id="graphs-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-4">
<!-- First three graphs -->
<div class="bg-white p-4 shadow rounded">
<h4 class="text-md font-semibold mb-4">Comparison of All Models by Department</h4>
<select id="departmentSelector" class="mb-4 p-2 border rounded">
@foreach($departments as $department)
<option value="{{ $department->id }}">{{ $department->name }}</option>
@endforeach
</select>
<canvas id="comparisonChart"></canvas>
</div>
<div class="bg-white p-4 shadow rounded">
<h4 class="text-md font-semibold mb-4">Total Contribution by Department</h4>
<select id="modelSelector" class="mb-4 p-2 border rounded">
<option value="all">All Categories</option>
<option value="ActivitiesAttended">Activities Attended</option>
<option value="ActivitiesOrganised">Activities Organised</option>
<option value="BooksPublished">Books Published</option>
<option value="ExternalEngagement">External Engagement</option>
<option value="IvOrganised">IV Organised</option>
<option value="OnlineCourse">Online Courses</option>
<option value="Patent">Patents</option>
<option value="Publication">Publications</option>
</select>
<canvas id="contributionChart"></canvas>
</div>
<div class="bg-white p-4 shadow rounded"> <div class="bg-white p-4 shadow rounded">
<h4 class="text-md font-semibold mb-4">Activities Attended by Department</h4> <h4 class="text-md font-semibold mb-4">Activities Attended by Department</h4>
<canvas id="activitiesAttendedChart"></canvas> <canvas id="activitiesAttendedChart"></canvas>
</div> </div>
<div class="bg-white p-4 shadow rounded">
<!-- Hidden graphs (initially hidden) -->
<div class="bg-white p-4 shadow rounded hidden">
<h4 class="text-md font-semibold mb-4">Activities Organised by Department</h4> <h4 class="text-md font-semibold mb-4">Activities Organised by Department</h4>
<canvas id="activitiesOrganisedChart"></canvas> <canvas id="activitiesOrganisedChart"></canvas>
</div> </div>
<div class="bg-white p-4 shadow rounded"> <div class="bg-white p-4 shadow rounded hidden">
<h4 class="text-md font-semibold mb-4">Iv Organised by Department</h4> <h4 class="text-md font-semibold mb-4">Iv Organised by Department</h4>
<canvas id="ivOrganisedChart"></canvas> <canvas id="ivOrganisedChart"></canvas>
</div> </div>
<div class="bg-white p-4 shadow rounded"> <div class="bg-white p-4 shadow rounded hidden">
<h4 class="text-md font-semibold mb-4">Publications by Department</h4> <h4 class="text-md font-semibold mb-4">Publications by Department</h4>
<canvas id="publicationsChart"></canvas> <canvas id="publicationsChart"></canvas>
</div> </div>
<div class="bg-white p-4 shadow rounded"> <div class="bg-white p-4 shadow rounded hidden">
<h4 class="text-md font-semibold mb-4">Books Published by Department</h4> <h4 class="text-md font-semibold mb-4">Books Published by Department</h4>
<canvas id="booksPublishedChart"></canvas> <canvas id="booksPublishedChart"></canvas>
</div> </div>
<div class="bg-white p-4 shadow rounded"> <div class="bg-white p-4 shadow rounded hidden">
<h4 class="text-md font-semibold mb-4">External Engagement by Department</h4> <h4 class="text-md font-semibold mb-4">External Engagement by Department</h4>
<canvas id="externalEngagementChart"></canvas> <canvas id="externalEngagementChart"></canvas>
</div> </div>
<div class="bg-white p-4 shadow rounded"> <div class="bg-white p-4 shadow rounded hidden">
<h4 class="text-md font-semibold mb-4">Online Course by Department</h4> <h4 class="text-md font-semibold mb-4">Online Course by Department</h4>
<canvas id="onlineCourseChart"></canvas> <canvas id="onlineCourseChart"></canvas>
</div> </div>
<div class="bg-white p-4 shadow rounded"> <div class="bg-white p-4 shadow rounded hidden">
<h4 class="text-md font-semibold mb-4">Patents by Department</h4> <h4 class="text-md font-semibold mb-4">Patents by Department</h4>
<canvas id="patentsChart"></canvas> <canvas id="patentsChart"></canvas>
</div> </div>
<!-- Add more charts as needed --> </div>
<!-- Load More Button -->
<div class="text-center mt-4">
<button id="loadMoreGraphs" class="bg-black text-white px-4 py-2 rounded">Load More</button>
</div> </div>
</div> </div>
</div> </div>
@@ -65,9 +97,158 @@
</style> --> </style> -->
@section('scripts') @section('scripts')
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Comparison Chart Script
const departmentSelector = document.getElementById('departmentSelector');
function fetchComparisonData(departmentId) {
fetch(`{{ route('admin.analytics.comparison', ['department_id' => '']) }}${departmentId}`)
.then(response => response.json())
.then(data => {
const ctx = document.getElementById('comparisonChart').getContext('2d');
if (window.comparisonChartInstance) {
window.comparisonChartInstance.destroy();
}
window.comparisonChartInstance = new Chart(ctx, {
type: 'pie',
data: {
labels: data.labels,
datasets: [{
label: 'Comparison by Department',
data: data.values,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
plugins: [ChartDataLabels],
options: {
plugins: {
legend: {
position: 'bottom',
},
tooltip: {
callbacks: {
label: function(tooltipItem) {
return `${tooltipItem.label}: ${tooltipItem.raw}`;
}
}
},
datalabels: {
color: '#000',
font: {
weight: 'bold'
},
formatter: (value, ctx) => {
return value;
}
}
},
responsive: true,
}
});
// Update or create the total element
let comparisonTotal = document.getElementById('comparisonTotal');
if (!comparisonTotal) {
comparisonTotal = document.createElement('p');
comparisonTotal.id = 'comparisonTotal';
comparisonTotal.classList.add('text-center', 'font-bold', 'mt-2');
document.getElementById('comparisonChart').parentElement.appendChild(comparisonTotal);
}
comparisonTotal.textContent = `Total: ${data.total}`;
});
}
// Initial fetch for department 1
fetchComparisonData(1);
// Update chart on department change
departmentSelector.addEventListener('change', function() {
fetchComparisonData(this.value);
});
// Contribution Chart Script
const modelSelector = document.getElementById('modelSelector');
function fetchContributionData(model) {
fetch(`{{ route('admin.analytics.contribution', ['model' => '']) }}${model}`)
.then(response => response.json())
.then(data => {
const ctx = document.getElementById('contributionChart').getContext('2d');
if (window.contributionChartInstance) {
window.contributionChartInstance.destroy();
}
window.contributionChartInstance = new Chart(ctx, {
type: 'pie',
data: {
labels: data.labels,
datasets: [{
label: 'Total Contribution by Department',
data: data.values,
borderWidth: 1
}]
},
plugins: [ChartDataLabels],
options: {
plugins: {
legend: {
position: 'bottom',
display: true
},
tooltip: {
callbacks: {
label: function(tooltipItem) {
return `${tooltipItem.label}: ${tooltipItem.raw}`;
}
}
}
},
datalabels: {
color: '#000',
font: {
weight: 'bold'
},
formatter: (value, ctx) => {
return value;
}
},
responsive: true,
}
});
// Update or create the total element
let contributionTotal = document.getElementById('contributionTotal');
if (!contributionTotal) {
contributionTotal = document.createElement('p');
contributionTotal.id = 'contributionTotal';
contributionTotal.classList.add('text-center', 'font-bold', 'mt-2');
document.getElementById('contributionChart').parentElement.appendChild(contributionTotal);
}
contributionTotal.textContent = `Total: ${data.total}`;
});
}
// Initial fetch for all categories
fetchContributionData('all');
// Update chart on model change
modelSelector.addEventListener('change', function() {
fetchContributionData(this.value);
});
// Fetch data for Activities Attended // Fetch data for Activities Attended
fetch("{{ route('admin.analytics.activitiesAttended') }}") fetch("{{ route('admin.analytics.activitiesAttended') }}")
.then(response => response.json()) .then(response => response.json())
@@ -467,5 +648,16 @@
document.getElementById('patentsChart').parentElement.appendChild(activitiesTotal); document.getElementById('patentsChart').parentElement.appendChild(activitiesTotal);
}); });
}); });
// Load More Button Script
document.addEventListener('DOMContentLoaded', function() {
const loadMoreButton = document.getElementById('loadMoreGraphs');
const hiddenGraphs = document.querySelectorAll('#graphs-container .hidden');
loadMoreButton.addEventListener('click', function() {
hiddenGraphs.forEach(graph => graph.classList.remove('hidden')); // Show hidden graphs
loadMoreButton.style.display = 'none'; // Hide the button
});
});
</script> </script>
@endsection @endsection

View File

@@ -128,6 +128,7 @@ Route::middleware(['auth', CheckRole::class . ':Admin'])->group(function () {
Route::get('/admin/Patents/{id}/edit', [PatentsController::class, 'edit'])->name('admin.Patents.edit'); Route::get('/admin/Patents/{id}/edit', [PatentsController::class, 'edit'])->name('admin.Patents.edit');
Route::put('/admin/Patents/{id}', [PatentsController::class, 'update'])->name('admin.Patents.update'); Route::put('/admin/Patents/{id}', [PatentsController::class, 'update'])->name('admin.Patents.update');
Route::delete('/admin/Patents/{id}', [PatentsController::class, 'destroy'])->name('admin.Patents.destroy'); Route::delete('/admin/Patents/{id}', [PatentsController::class, 'destroy'])->name('admin.Patents.destroy');
}); });
// Coordinator routes // Coordinator routes
@@ -282,4 +283,7 @@ Route::prefix('admin')->name('admin.')->group(function () {
Route::get('analytics/externalEngagement', [AdminController::class, 'analyticsExternalEngagement'])->name('analytics.externalEngagement'); Route::get('analytics/externalEngagement', [AdminController::class, 'analyticsExternalEngagement'])->name('analytics.externalEngagement');
Route::get('analytics/onlineCourse', [AdminController::class, 'analyticsOnlineCourse'])->name('analytics.onlineCourse'); Route::get('analytics/onlineCourse', [AdminController::class, 'analyticsOnlineCourse'])->name('analytics.onlineCourse');
Route::get('analytics/patent', [AdminController::class, 'analyticsPatent'])->name('analytics.patent'); Route::get('analytics/patent', [AdminController::class, 'analyticsPatent'])->name('analytics.patent');
Route::get('analytics/comparison', [AdminController::class, 'analyticsComparison'])->name('analytics.comparison');
Route::get('analytics/contribution', [AdminController::class, 'analyticsContribution'])->name('analytics.contribution');
}); });