819 lines
23 KiB
HTML
819 lines
23 KiB
HTML
{% extends "admin/base_site.html" %}
|
|
{% load static %}
|
|
{% load app_filters %}
|
|
{% block extrahead %}
|
|
{{ block.super }}
|
|
<meta name="viewport"
|
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
{% endblock %}
|
|
{% block extrastyle %}
|
|
{{ block.super }}
|
|
<!-- Bootstrap CSS -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
|
|
rel="stylesheet">
|
|
<!-- Font Awesome -->
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
|
|
rel="stylesheet" />
|
|
<style>
|
|
:root {
|
|
--primary: #2196F3;
|
|
--primary-light: #BBDEFB;
|
|
--primary-dark: #1976D2;
|
|
--secondary: #607D8B;
|
|
--success: #4CAF50;
|
|
--info: #00BCD4;
|
|
--warning: #FFC107;
|
|
--danger: #F44336;
|
|
--light: #FAFAFA;
|
|
--dark: #212121;
|
|
--gray: #9E9E9E;
|
|
}
|
|
|
|
body {
|
|
background-color: var(--light);
|
|
color: var(--dark);
|
|
}
|
|
|
|
.content-card {
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
padding: 24px;
|
|
margin-bottom: 24px;
|
|
transition: box-shadow 0.3s ease;
|
|
}
|
|
|
|
.content-card:hover {
|
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
|
}
|
|
|
|
.welcome-section {
|
|
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
|
|
color: white;
|
|
padding: 32px;
|
|
border-radius: 8px;
|
|
margin-bottom: 32px;
|
|
}
|
|
|
|
.summary-card {
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
|
}
|
|
|
|
.summary-card:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
}
|
|
|
|
.summary-card .card-header {
|
|
background: none;
|
|
border-bottom: 1px solid rgba(0,0,0,0.05);
|
|
padding: 16px;
|
|
}
|
|
|
|
.summary-card .card-body {
|
|
padding: 24px;
|
|
}
|
|
|
|
.stat-number {
|
|
font-size: 2.5rem;
|
|
font-weight: 700;
|
|
color: var(--primary);
|
|
}
|
|
|
|
.stat-label {
|
|
color: var(--secondary);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.status-badge {
|
|
padding: 6px 12px;
|
|
border-radius: 16px;
|
|
font-size: 0.8rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.completed { background: #E8F5E9; color: #2E7D32; }
|
|
.ongoing { background: #FFF3E0; color: #E65100; }
|
|
.upcoming { background: #E3F2FD; color: #1565C0; }
|
|
|
|
.leave-pending { background: #FFF8E1; color: #F57F17; }
|
|
.leave-approved { background: #E8F5E9; color: #2E7D32; }
|
|
.leave-rejected { background: #FFEBEE; color: #C62828; }
|
|
|
|
.btn-primary { background-color: var(--primary); border-color: var(--primary); }
|
|
.btn-success { background-color: var(--success); border-color: var(--success); }
|
|
.btn-info { background-color: var(--info); border-color: var(--info); }
|
|
.btn-warning { background-color: var(--warning); border-color: var(--warning); }
|
|
.btn-danger { background-color: var(--danger); border-color: var(--danger); }
|
|
|
|
.progress {
|
|
height: 8px;
|
|
background-color: var(--primary-light);
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.progress-bar {
|
|
background-color: var(--primary);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.table th {
|
|
color: var(--secondary);
|
|
font-weight: 600;
|
|
border-bottom-width: 1px;
|
|
}
|
|
|
|
.table td {
|
|
vertical-align: middle;
|
|
}
|
|
|
|
/*.bottom-nav {*/
|
|
/* position: fixed;*/
|
|
/* bottom: 0;*/
|
|
/* left: 0;*/
|
|
/* right: 0;*/
|
|
/* background: white;*/
|
|
/* box-shadow: 0 -2px 10px rgba(0,0,0,0.1);*/
|
|
/* z-index: 1000;*/
|
|
/* padding: 12px 0;*/
|
|
/*}*/
|
|
|
|
/*.nav-container {*/
|
|
/* display: flex;*/
|
|
/* justify-content: space-around;*/
|
|
/* max-width: 100%;*/
|
|
/* margin: 0 auto;*/
|
|
/*}*/
|
|
/**/
|
|
/*.nav-item {*/
|
|
/* color: var(--secondary);*/
|
|
/* text-decoration: none;*/
|
|
/* text-align: center;*/
|
|
/* padding: 8px 16px;*/
|
|
/* border-radius: 8px;*/
|
|
/* transition: all 0.3s ease;*/
|
|
/*}*/
|
|
/**/
|
|
/*.nav-item.active {*/
|
|
/* color: var(--primary);*/
|
|
/* background: rgba(33, 150, 243, 0.1);*/
|
|
/*}*/
|
|
/**/
|
|
/*.nav-item i {*/
|
|
/* font-size: 1.4rem;*/
|
|
/* margin-bottom: 4px;*/
|
|
/*}*/
|
|
/**/
|
|
/*.nav-item span {*/
|
|
/* display: block;*/
|
|
/* font-size: 0.8rem;*/
|
|
/*}*/
|
|
|
|
/* Teacher Ratings Section */
|
|
.teacher-rating-card {
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.teacher-rating-card:hover {
|
|
transform: translateY(-4px);
|
|
}
|
|
|
|
/* Monthly Statistics Section */
|
|
.stat-box {
|
|
background: white;
|
|
border-radius: 8px;
|
|
padding: 24px;
|
|
text-align: center;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.stat-box:hover {
|
|
transform: translateY(-4px);
|
|
}
|
|
|
|
.stat-box i {
|
|
font-size: 2.5rem;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
/* Institute Feedback Section */
|
|
.feedback-card {
|
|
background: white;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.rating-stars i {
|
|
color: var(--warning);
|
|
margin-right: 2px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.welcome-section h2 {
|
|
font-size: 1.5rem;
|
|
}
|
|
.summary-card .card-body {
|
|
padding: 16px;
|
|
}
|
|
.stat-number {
|
|
font-size: 2rem;
|
|
}
|
|
.content-card {
|
|
padding: 16px;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
{% block content %}
|
|
<div class="container-fluid py-4">
|
|
<!-- Welcome Section -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="content-card welcome-section">
|
|
<div class="d-flex justify-content-between align-items-center flex-wrap">
|
|
<div class="flex-grow-1">
|
|
<h2 class="mb-1">Welcome, Admin!</h2>
|
|
<p class="mb-0">Student Management Dashboard</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Quick Stats Row -->
|
|
<div class="row mb-4">
|
|
<!-- Student Stats -->
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="summary-card h-100">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-users text-primary me-2"></i>Students
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<div class="stat-number">{{ total_students }}</div>
|
|
<div class="stat-label">Total Students</div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3">
|
|
<div class="d-flex justify-content-between mb-2">
|
|
<span>Active</span>
|
|
<span class="badge bg-success">{{ active_students }}</span>
|
|
</div>
|
|
<div class="d-flex justify-content-between mb-2">
|
|
<span>Completed</span>
|
|
<span class="badge bg-info">{{ completed_students }}</span>
|
|
</div>
|
|
<div class="d-flex justify-content-between">
|
|
<span>On Leave</span>
|
|
<span class="badge bg-warning">{{ on_leave_students }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Course Stats -->
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="summary-card h-100">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-book text-success me-2"></i>Courses
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<div class="stat-number">{{ total_courses }}</div>
|
|
<div class="stat-label">Total Courses</div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3">
|
|
<div class="d-flex justify-content-between mb-2">
|
|
<span>Active</span>
|
|
<span class="badge bg-success">{{ active_courses }}</span>
|
|
</div>
|
|
<div class="d-flex justify-content-between">
|
|
<span>Completed</span>
|
|
<span class="badge bg-info">{{ completed_courses }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Staff Stats -->
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="summary-card h-100">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-chalkboard-teacher text-info me-2"></i>Staff
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<div class="stat-number">{{ total_staff }}</div>
|
|
<div class="stat-label">Total Staff</div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3">
|
|
<div class="d-flex justify-content-between mb-2">
|
|
<span>Active</span>
|
|
<span class="badge bg-success">{{ active_staff }}</span>
|
|
</div>
|
|
<div class="d-flex justify-content-between">
|
|
<span>On Leave</span>
|
|
<span class="badge bg-warning">{{ staff_on_leave }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Attendance Stats -->
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="summary-card h-100">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-calendar-check text-warning me-2"></i>Attendance
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<div class="stat-number">{{ total_classes_today }}</div>
|
|
<div class="stat-label">Classes Today</div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3">
|
|
<div class="d-flex justify-content-between mb-2">
|
|
<span>Students Present</span>
|
|
<span class="badge bg-success">{{ students_present }}/{{ total_students_today }}</span>
|
|
</div>
|
|
<div class="d-flex justify-content-between">
|
|
<span>Attendance Rate</span>
|
|
<span class="badge {% if attendance_rate >= 80 %}bg-success{% elif attendance_rate >= 60 %}bg-warning{% else %}bg-danger{% endif %}">
|
|
{{ attendance_rate }}%
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Quick Actions -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="content-card">
|
|
<h5 class="mb-4">
|
|
<i class="fas fa-bolt text-warning me-2"></i>Quick Actions
|
|
</h5>
|
|
<div class="row g-3">
|
|
<div class="col-md-3">
|
|
<a href="/app/student/add/" class="btn btn-primary w-100 py-3">
|
|
<i class="fas fa-user-plus mb-2 d-block"></i>
|
|
Add New Student
|
|
</a>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<a href="/app/staff/add/" class="btn btn-success w-100 py-3">
|
|
<i class="fas fa-user-tie mb-2 d-block"></i>
|
|
Add New Staff
|
|
</a>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<a href="/app/course/add/" class="btn btn-info w-100 py-3">
|
|
<i class="fas fa-book mb-2 d-block"></i>
|
|
Add New Course
|
|
</a>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<a href="/app/batch/add/" class="btn btn-warning w-100 py-3">
|
|
<i class="fas fa-users mb-2 d-block"></i>
|
|
Add New Batch
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Recent Activity and Course Progress -->
|
|
<div class="row">
|
|
<!-- Course Progress -->
|
|
<div class="col-xl-8 mb-4">
|
|
<div class="content-card">
|
|
<h5 class="mb-4">
|
|
<i class="fas fa-graduation-cap text-primary me-2"></i>Course Progress
|
|
</h5>
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Course</th>
|
|
<th>Students</th>
|
|
<th>Progress</th>
|
|
<th>Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for progress in course_progress %}
|
|
<tr>
|
|
<td>{{ progress.course.name }}</td>
|
|
<td>{{ progress.total_students }}</td>
|
|
<td>
|
|
<div class="progress" style="height: 8px;">
|
|
<div class="progress-bar bg-primary" role="progressbar" style="width: {{ progress.average_progress }}%" aria-valuenow="{{ progress.average_progress }}" aria-valuemin="0" aria-valuemax="100">
|
|
</div>
|
|
</div>
|
|
<small class="text-muted">{{ progress.average_progress }}%</small>
|
|
</td>
|
|
<td>
|
|
<span class="status-badge {% if progress.average_progress == 100 %}completed{% elif progress.average_progress > 0 %}ongoing{% else %}upcoming{% endif %}">
|
|
{% if progress.average_progress == 100 %}
|
|
Completed
|
|
{% elif progress.average_progress > 0 %}
|
|
In Progress
|
|
{% else %}
|
|
Not Started
|
|
{% endif %}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="4" class="text-center py-3">No course progress data available</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Recent Activity -->
|
|
<div class="col-xl-4 mb-4">
|
|
<div class="content-card">
|
|
<h5 class="mb-4">
|
|
<i class="fas fa-history text-success me-2"></i>Recent Activity
|
|
</h5>
|
|
<div class="recent-activity" style="max-height: 400px; overflow-y: auto;">
|
|
{% for activity in recent_activities %}
|
|
<div class="d-flex align-items-start mb-3 pb-3 border-bottom">
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-1">{{ activity.title }}</h6>
|
|
<p class="mb-0 text-muted small">{{ activity.description }}</p>
|
|
<small class="text-muted">{{ activity.timestamp|timesince }} ago</small>
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<p class="text-center text-muted">No recent activity</p>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Pending Leave Requests -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="content-card">
|
|
<h5 class="mb-4">
|
|
<i class="fas fa-calendar-alt text-warning me-2"></i>Pending Leave Requests
|
|
</h5>
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Type</th>
|
|
<th>Date</th>
|
|
<th>Reason</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for leave in pending_student_leaves %}
|
|
<tr>
|
|
<td>{{ leave.student.name }}</td>
|
|
<td>
|
|
<span class="badge bg-info">Student</span>
|
|
</td>
|
|
<td>{{ leave.date|date:"M d, Y" }}</td>
|
|
<td>{{ leave.message }}</td>
|
|
<td>
|
|
<form method="post" action="{% url 'approve_student_leave' leave.id %}" class="d-inline">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-sm btn-success me-1">
|
|
<i class="fas fa-check"></i>
|
|
</button>
|
|
</form>
|
|
<form method="post" action="{% url 'reject_student_leave' leave.id %}" class="d-inline">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-sm btn-danger">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% for leave in pending_staff_leaves %}
|
|
<tr>
|
|
<td>{{ leave.staff.name }}</td>
|
|
<td>
|
|
<span class="badge bg-primary">Staff</span>
|
|
</td>
|
|
<td>{{ leave.date|date:"M d, Y" }}</td>
|
|
<td>{{ leave.message }}</td>
|
|
<td>
|
|
<form method="post" action="{% url 'approve_staff_leave' leave.id %}" class="d-inline">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-sm btn-success me-1">
|
|
<i class="fas fa-check"></i>
|
|
</button>
|
|
</form>
|
|
<form method="post" action="{% url 'reject_staff_leave' leave.id %}" class="d-inline">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-sm btn-danger">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% if not pending_student_leaves and not pending_staff_leaves %}
|
|
<tr>
|
|
<td colspan="5" class="text-center py-3">No pending leave requests</td>
|
|
</tr>
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Notice Board -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="content-card">
|
|
<h5 class="mb-4">
|
|
<i class="fas fa-bullhorn text-primary me-2"></i>Notice Board
|
|
</h5>
|
|
<form method="post" action="{% url 'add_notice' %}" class="mb-4" enctype="multipart/form-data">
|
|
{% csrf_token %}
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<input type="text" class="form-control" name="title" placeholder="Notice Title" required>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<input type="text" class="form-control" name="message" placeholder="Notice Message" required>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<input type="file" class="form-control" name="image" accept="image/*">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<button type="submit" class="btn btn-primary w-100">
|
|
<i class="fas fa-plus me-2"></i>Add Notice
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
<div class="notices-list">
|
|
{% for notice in notices %}
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
<h6 class="mb-0">{{ notice.title }}</h6>
|
|
<small class="text-muted">{{ notice.created_at|date:"M d, Y" }}</small>
|
|
</div>
|
|
{% if notice.image %}
|
|
<img src="{{ notice.image.url }}" alt="Notice Image" class="img-fluid rounded mb-2" style="max-height: 200px;">
|
|
{% endif %}
|
|
<p class="mb-2">{{ notice.message }}</p>
|
|
<button class="btn btn-sm btn-outline-danger" onclick="deleteNotice({{ notice.id }})">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<p class="text-center text-muted">No notices available</p>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Teacher Ratings Section -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="content-card">
|
|
<h5 class="mb-4">
|
|
<i class="fas fa-star text-warning me-2"></i>Teacher Ratings
|
|
</h5>
|
|
<div class="row">
|
|
{% for teacher in teacher_ratings %}
|
|
<div class="col-md-4 mb-4">
|
|
<div class="teacher-rating-card">
|
|
<div class="d-flex align-items-center mb-3">
|
|
{% if teacher.image %}
|
|
<img src="{{ teacher.image.url }}" alt="{{ teacher.name }}" class="rounded-circle me-3" style="width: 60px; height: 60px; object-fit: cover;">
|
|
{% else %}
|
|
<div class="rounded-circle bg-light d-flex align-items-center justify-content-center me-3" style="width: 60px; height: 60px;">
|
|
<i class="fas fa-user text-secondary"></i>
|
|
</div>
|
|
{% endif %}
|
|
<div>
|
|
<h6 class="mb-1">{{ teacher.name }}</h6>
|
|
<small class="text-muted">{{ teacher.designation }}</small>
|
|
</div>
|
|
</div>
|
|
<div class="rating-info mb-3">
|
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
<span class="text-muted">Average Rating</span>
|
|
<span class="fw-bold">{{ teacher.avg_rating|floatformat:1 }}/5.0</span>
|
|
</div>
|
|
<div class="rating-stars mb-2">
|
|
{% for i in "12345"|make_list %}
|
|
<i class="{% if forloop.counter <= teacher.avg_rating %}fas{% else %}far{% endif %} fa-star"></i>
|
|
{% endfor %}
|
|
</div>
|
|
<div class="progress">
|
|
<div class="progress-bar bg-warning" role="progressbar" style="width: {{ teacher.avg_rating|multiply:20 }}%" aria-valuenow="{{ teacher.avg_rating }}" aria-valuemin="0" aria-valuemax="5">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="rating-stats">
|
|
<div class="d-flex justify-content-between mb-2">
|
|
<small class="text-muted">Total Reviews</small>
|
|
<small>{{ teacher.total_reviews }}</small>
|
|
</div>
|
|
<div class="d-flex justify-content-between">
|
|
<small class="text-muted">Students Taught</small>
|
|
<small>{{ teacher.total_students }}</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<div class="col-12">
|
|
<p class="text-center text-muted">No teacher ratings available</p>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Monthly Statistics -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="content-card">
|
|
<h5 class="mb-4">
|
|
<i class="fas fa-chart-bar text-info me-2"></i>Monthly Statistics
|
|
</h5>
|
|
<div class="row">
|
|
<div class="col-md-3 mb-3">
|
|
<div class="stat-box">
|
|
<i class="fas fa-user-plus text-primary"></i>
|
|
<h3 class="mb-2">{{ monthly_stats.new_students }}</h3>
|
|
<p class="text-muted mb-0">New Students</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 mb-3">
|
|
<div class="stat-box">
|
|
<i class="fas fa-user-tie text-success"></i>
|
|
<h3 class="mb-2">{{ monthly_stats.new_staff }}</h3>
|
|
<p class="text-muted mb-0">New Staff</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 mb-3">
|
|
<div class="stat-box">
|
|
<i class="fas fa-calendar-check text-warning"></i>
|
|
<h3 class="mb-2">{{ monthly_stats.attendance_rate }}%</h3>
|
|
<p class="text-muted mb-0">Attendance Rate</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 mb-3">
|
|
<div class="stat-box">
|
|
<i class="fas fa-calendar-alt text-danger"></i>
|
|
<h3 class="mb-2">{{ monthly_stats.leave_requests }}</h3>
|
|
<p class="text-muted mb-0">Leave Requests</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Institute Feedback -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="content-card">
|
|
<h5 class="mb-4">
|
|
<i class="fas fa-comments text-primary me-2"></i>Institute Feedback
|
|
</h5>
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Type</th>
|
|
<th>Category</th>
|
|
<th>Name</th>
|
|
<th>Rating</th>
|
|
<th>Feedback</th>
|
|
<th>Date</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for feedback in recent_institute_feedback %}
|
|
<tr>
|
|
<td>
|
|
<span class="badge {% if feedback.user_type == 'student' %}bg-info{% else %}bg-primary{% endif %}">
|
|
{{ feedback.user_type|title }}
|
|
</span>
|
|
</td>
|
|
<td>{{ feedback.feedback_type }}</td>
|
|
<td>{{ feedback.display_name }}</td>
|
|
<td>
|
|
<div class="rating-stars">
|
|
{% for i in "12345"|make_list %}
|
|
<i class="{% if forloop.counter <= feedback.rating %}fas{% else %}far{% endif %} fa-star"></i>
|
|
{% endfor %}
|
|
</div>
|
|
</td>
|
|
<td>{{ feedback.feedback_text|truncatechars:100 }}</td>
|
|
<td>{{ feedback.created_at|date:"M d, Y" }}</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="6" class="text-center py-3">No institute feedback available</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Bottom Navigation -->
|
|
<nav class="bottom-nav d-md-none">
|
|
<div class="nav-container">
|
|
<a href="#" class="nav-item active">
|
|
<i class="fas fa-home d-block"></i>
|
|
<span>Home</span>
|
|
</a>
|
|
<a href="#" class="nav-item">
|
|
<i class="fas fa-users d-block"></i>
|
|
<span>Students</span>
|
|
</a>
|
|
<a href="#" class="nav-item">
|
|
<i class="fas fa-chalkboard-teacher d-block"></i>
|
|
<span>Staff</span>
|
|
</a>
|
|
<a href="#" class="nav-item">
|
|
<i class="fas fa-book d-block"></i>
|
|
<span>Courses</span>
|
|
</a>
|
|
</div>
|
|
</nav>
|
|
{% endblock %}
|
|
{% block extrajs %}
|
|
{{ block.super }}
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
function deleteNotice(noticeId) {
|
|
if (confirm('Are you sure you want to delete this notice?')) {
|
|
fetch(`/app/delete-notice/${noticeId}/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
location.reload();
|
|
} else {
|
|
alert('Failed to delete notice');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while deleting the notice');
|
|
});
|
|
}
|
|
}
|
|
</script>
|
|
{% endblock %}
|