Updated Google Scholar Integration,Updated Admin and HOD Dashboard, Added Google Auth: Login Controller and Routes

This commit is contained in:
tanmaychinchore
2025-11-18 22:24:53 +05:30
parent 9ee3d3eda4
commit 34394e6abf
9 changed files with 1347 additions and 49 deletions

View File

@@ -1,22 +1,223 @@
@extends('layouts.app')
@section('header')
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Coordinator Dashboard
</h2>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Coordinator Dashboard
</h2>
@endsection
@section('content')
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900">
Welcome, Coordinator! Manage department-related tasks here.
</div>
</div>
<div class="mt-6">
<a href="{{ route('departments.index') }}" class="text-blue-500 underline">View Departments</a><br>
<a href="{{ route('users.index') }}" class="text-blue-500 underline">View Faculty</a><br>
<a href="{{ route('profile.edit') }}" class="text-blue-500 underline">Edit Profile</a>
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900">
Welcome, Coordinator! Manage department-related tasks here.
</div>
</div>
<!-- Graphs Section -->
<div class="mt-6">
<h3 class="text-lg font-semibold">Analytics</h3>
<div id="graphs-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 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>
<div class="flex flex-row sm:flex-row sm:items-center sm:justify-between">
<select id="departmentSelector" class="mb-4 px-7 border rounded">
@foreach($departments as $department)
<option value="{{ $department->id }}">{{ $department->name }}</option>
@endforeach
</select>
<select id="comparisonYearSelector" class="mb-4 px-7 border rounded">
<option value="all">All Years</option>
@foreach($years as $year)
<option value="{{ $year }}">{{ $year }}</option>
@endforeach
</select>
</div>
<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>
<div class="flex flex-row sm:flex-row sm:items-center sm:justify-between">
<select id="modelSelector" class="mb-4 sm:mb-0 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>
<select id="contributionYearSelector" class="mb-4 sm:ml-4 px-7 border rounded">
<option value="all">All Years</option>
@foreach($years as $year)
<option value="{{ $year }}">{{ $year }}</option>
@endforeach
</select>
</div>
<canvas id="contributionChart"></canvas>
</div>
</div>
</div>
@endsection
@section('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
const departmentSelector = document.getElementById('departmentSelector');
const comparisonYearSelector = document.getElementById('comparisonYearSelector');
const modelSelector = document.getElementById('modelSelector');
const contributionYearSelector = document.getElementById('contributionYearSelector');
// Use coordinator route names (must exist in routes/web.php)
const comparisonBaseUrl = "{{ route('coordinator.analytics.comparison') }}";
const contributionBaseUrl = "{{ route('coordinator.analytics.contribution') }}";
function fetchComparisonData(departmentId, year) {
const yearParam = year === 'all' ? '' : `&year=${year}`;
const url = departmentId
? `${comparisonBaseUrl}?department_id=${departmentId}${yearParam}`
: `${comparisonBaseUrl}?${yearParam}`;
fetch(url)
.then(response => {
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.json();
})
.then(data => {
const ctx = document.getElementById('comparisonChart').getContext('2d');
if (window.comparisonChartInstance) window.comparisonChartInstance.destroy();
const modelPages = [
'ActivitiesAttendedResponses',
'ActivitiesOrganisedResponses',
'BooksPublishedResponses',
'ExternalEngagementResponses',
'IvOrganisedResponses',
'OnlineCoursesResponses',
'PatentsResponses',
'PublicationsResponses'
];
// Redirect to coordinator pages
const barLinks = modelPages.map(page => `/coordinator/${page}`);
window.comparisonChartInstance = new Chart(ctx, {
type: 'bar',
data: {
labels: data.labels,
datasets: [{
label: 'Comparison by Department',
data: data.values,
}]
},
plugins: [ChartDataLabels],
options: {
plugins: { legend: { display: false } },
responsive: true,
scales: { y: { beginAtZero: true } },
onClick: function(evt, elements) {
if (elements.length > 0) {
const idx = elements[0].index;
const deptId = departmentSelector ? departmentSelector.value : departmentId;
if (idx < barLinks.length) window.location.href = `${barLinks[idx]}?department_id=${deptId}`;
}
}
}
});
// show total
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}`;
})
.catch(err => {
console.error('Comparison fetch error:', err);
});
}
function fetchContributionData(model, year) {
const yearParam = year === 'all' ? '' : `&year=${year}`;
const url = `${contributionBaseUrl}?model=${model}${yearParam}`;
fetch(url)
.then(response => {
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.json();
})
.then(data => {
const ctx = document.getElementById('contributionChart').getContext('2d');
if (window.contributionChartInstance) window.contributionChartInstance.destroy();
// map labels to coordinator pages (adjust if needed)
const barLinks = data.labels.map((label, idx) => `/coordinator/contribution/${idx+1}`);
window.contributionChartInstance = new Chart(ctx, {
type: 'bar',
data: {
labels: data.labels,
datasets: [{ label: 'Total Contribution by Department', data: data.values }]
},
plugins: [ChartDataLabels],
options: {
plugins: { legend: { display: false } },
responsive: true,
scales: { y: { beginAtZero: true } },
onClick: function(evt, elements) {
if (elements.length > 0) {
const idx = elements[0].index;
window.location.href = barLinks[idx];
}
}
}
});
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}`;
})
.catch(err => {
console.error('Contribution fetch error:', err);
});
}
// INITIAL FETCH: use the selected department (not hardcoded 1)
const initialDept = departmentSelector ? departmentSelector.value : null;
const initialYear = comparisonYearSelector ? comparisonYearSelector.value : 'all';
if (initialDept) {
fetchComparisonData(initialDept, initialYear);
} else {
// fallback: let server infer (coordinator filter), call without department_id
fetchComparisonData('', initialYear);
}
// initial contribution
const initModel = modelSelector ? modelSelector.value : 'all';
const initContribYear = contributionYearSelector ? contributionYearSelector.value : 'all';
fetchContributionData(initModel, initContribYear);
// Event listeners
if (departmentSelector) departmentSelector.addEventListener('change', () => fetchComparisonData(departmentSelector.value, comparisonYearSelector.value));
if (comparisonYearSelector) comparisonYearSelector.addEventListener('change', () => fetchComparisonData(departmentSelector.value, comparisonYearSelector.value));
if (modelSelector) modelSelector.addEventListener('change', () => fetchContributionData(modelSelector.value, contributionYearSelector.value));
if (contributionYearSelector) contributionYearSelector.addEventListener('change', () => fetchContributionData(modelSelector.value, contributionYearSelector.value));
});
</script>
@endsection