Files
2025-04-20 17:46:30 +05:45

1337 lines
55 KiB
HTML

{% extends 'shared/base.html' %}
{% load static %}
{% load tz %}
{% load app_filters %}
{% block extra_js %}
<script src="{% static 'js/rating.js' %}"></script>
<script src="{% static 'js/student_modals.js' %}"></script>
{% endblock %}
{% block content %}
<!-- Add CSRF token to the page -->
{% csrf_token %}
<div class="container-fluid py-4">
<!-- Welcome Section -->
{% include 'shared/welcome_section.html' with user=parent %}
<!-- Dashboard Content -->
<div id="dashboardSection" class="content-section active">
<!-- Summary Cards -->
<div class="row mb-4">
<!-- Students Summary Card -->
<div class="col-md-4 col-lg-3 mb-3">
<div class="summary-card h-100">
<div class="card-header">
<h5 class="card-title mb-0 small"><i class="fas fa-users me-1"></i> Students</h5>
</div>
<div class="card-body p-2">
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<span class="d-block text-muted small">Total Students</span>
<h3>{{ attendance_summary.total_students }}</h3>
</div>
<div class="text-end">
<span class="d-block text-muted small">Present Today</span>
<h3 class="text-success">{{ attendance_summary.students_present_today }}</h3>
</div>
</div>
<div class="d-flex justify-content-between mb-2">
<small class="mb-0">Absent Today</small>
<span class="badge bg-danger p-2">{{ attendance_summary.students_absent_today }}</span>
</div>
</div>
</div>
</div>
<!-- Course Progress Card -->
<div class="col-md-4 col-lg-3 mb-3">
<div class="summary-card h-100">
<div class="card-header">
<h5 class="card-title mb-0 small"><i class="fas fa-graduation-cap me-1"></i> Course Progress</h5>
</div>
<div class="card-body p-2">
{% if course_progress %}
{% for progress in course_progress|slice:":3" %}
<div class="mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<small class="text-muted">{{ progress.student }} - {{ progress.course }}</small>
<span class="badge {% if progress.status == 'Completed' %}bg-success{% elif progress.status == 'In Progress' %}bg-warning{% else %}bg-secondary{% endif %}">
{{ progress.status }}
</span>
</div>
<div class="progress" style="height: 5px;">
<div class="progress-bar bg-primary" role="progressbar" style="width: {{ progress.progress }}%"></div>
</div>
<small class="text-muted">{{ progress.progress }}%</small>
</div>
{% endfor %}
{% if course_progress|length > 3 %}
<div class="text-center">
<small class="text-muted">+{{ course_progress|length|add:"-3" }} more courses</small>
</div>
{% endif %}
{% else %}
<p class="text-center text-muted mb-0">No course progress data available</p>
{% endif %}
</div>
</div>
</div>
<!-- Recent Leaves Card -->
<div class="col-md-4 col-lg-3 mb-3">
<div class="summary-card h-100">
<div class="card-header">
<h5 class="card-title mb-0 small"><i class="fas fa-calendar-minus me-1"></i> Recent Leaves</h5>
</div>
<div class="card-body p-2">
{% if recent_leaves %}
{% for leave in recent_leaves %}
<div class="mb-2">
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{ leave.student.name }}</small>
<span class="badge {% if leave.status == 1 %}bg-success{% elif leave.status == 2 %}bg-danger{% else %}bg-warning{% endif %}">
{% if leave.status == 1 %}Approved{% elif leave.status == 2 %}Rejected{% else %}Pending{% endif %}
</span>
</div>
<small class="text-muted d-block">{{ leave.start_date|date:"M d, Y" }} - {{ leave.end_date|date:"M d, Y" }}</small>
</div>
{% endfor %}
{% else %}
<p class="text-center text-muted mb-0">No recent leaves</p>
{% endif %}
</div>
</div>
</div>
<!-- Recent Notices Card -->
<div class="col-md-4 col-lg-3 mb-3">
<div class="summary-card h-100">
<div class="card-header">
<h5 class="card-title mb-0 small">
<i class="fas fa-bullhorn me-1"></i> Recent Notices
</h5>
</div>
<div class="card-body p-2">
{% if notices %}
{% for notice in notices|slice:":3" %}
<div class="notice-item mb-2 p-2 border-bottom">
<div class="d-flex justify-content-between align-items-start mb-1">
<h6 class="mb-0 text-primary">{{ notice.title|truncatechars:30 }}</h6>
<small class="text-muted">{{ notice.created_at|timesince }} ago</small>
</div>
<p class="mb-1 small text-muted">{{ notice.message|truncatechars:50 }}</p>
{% if notice.file %}
<a href="{{ notice.file.url }}" class="btn btn-sm btn-outline-primary btn-sm mt-1" target="_blank">
<i class="fas fa-download me-1"></i> Download
</a>
{% endif %}
</div>
{% endfor %}
{% if notices|length > 3 %}
<!-- <div class="text-center mt-2">
<button type="button" class="btn btn-sm btn-outline-primary" onclick="showSection('noticeSection')">
<i class="fas fa-bullhorn me-1"></i> View All Notices
</button>
</div> -->
{% endif %}
{% else %}
<div class="text-center py-3">
<i class="fas fa-bullhorn text-muted mb-2" style="font-size: 2rem;"></i>
<p class="text-muted mb-0">No notices available</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Students List -->
<div class="row mb-4">
<div class="col-12">
<div class="content-card">
<h4 class="card-title mb-3">
<i class="fas fa-users me-2"></i> My Children
</h4>
<div class="table-responsive">
<table class="table table-responsive">
<thead>
<tr>
<th>Name</th>
<th>Course</th>
<th>Current Period</th>
<th>Attendance</th>
<th>Course Progress</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for student_info in student_data %}
<tr data-student-id="{{ student_info.student.id }}">
<td>
<div class="d-flex align-items-center">
{% if student_info.student.image %}
<img src="{{ student_info.student.image.url }}" alt="{{ student_info.student.name }}" class="rounded-circle me-2" style="width: 32px; height: 32px;">
{% else %}
<div class="student-avatar me-2">
<i class="fas fa-user"></i>
</div>
{% endif %}
{{ student_info.student.name }}
</div>
</td>
<td>{{ student_info.student.course.name|default:"Not assigned" }}</td>
<td>
{% if student_info.student.course %}
{% if student_info.student.course.duration_type == 'Semester' %}
Semester {{ student_info.student.current_period }}
{% else %}
Year {{ student_info.student.current_period }}
{% endif %}
{% else %}
-
{% endif %}
</td>
<td>
{% with attended_classes=student_info.student.attendance_records.all|filter_attended|length %}
{% if student_info.student.course.duration_type == 'Semester' %}
{% with total_period_days=180 %}
{% with attendance_rate=attended_classes|div:total_period_days|multiply:100 %}
<div class="progress" style="height: 5px; width: 100px;">
<div class="progress-bar {% if attendance_rate < 75 %}bg-danger{% else %}bg-success{% endif %}"
role="progressbar"
style="width: {{ attendance_rate }}%">
</div>
</div>
<small class="text-muted">{{ attendance_rate|floatformat:1 }}%</small>
{% endwith %}
{% endwith %}
{% else %}
{% with total_period_days=365 %}
{% with attendance_rate=attended_classes|div:total_period_days|multiply:100 %}
<div class="progress" style="height: 5px; width: 100px;">
<div class="progress-bar {% if attendance_rate < 75 %}bg-danger{% else %}bg-success{% endif %}"
role="progressbar"
style="width: {{ attendance_rate }}%">
</div>
</div>
<small class="text-muted">{{ attendance_rate|floatformat:1 }}%</small>
{% endwith %}
{% endwith %}
{% endif %}
{% endwith %}
</td>
<td>
{% with tracking=student_info.student.course_trackings.first %}
{% if tracking %}
<div class="progress" style="height: 5px; width: 100px;">
<div class="progress-bar {% if tracking.completion_percentage >= 75 %}bg-success{% elif tracking.completion_percentage >= 50 %}bg-warning{% else %}bg-danger{% endif %}"
role="progressbar"
style="width: {{ tracking.completion_percentage }}%">
</div>
</div>
<small class="text-muted">{{ tracking.completion_percentage }}%</small>
{% else %}
<span class="text-muted">No data</span>
{% endif %}
{% endwith %}
</td>
<td>
<span class="badge {% if student_info.student.status == 'Active' %}bg-success{% elif student_info.student.status == 'Leave' %}bg-warning{% else %}bg-secondary{% endif %}">
{{ student_info.student.status }}
</span>
</td>
<td>
<button class="badge bg-primary border-0" onclick="viewStudentDetails({{ student_info.student.id }})">
<i class="fas fa-eye me-1"></i> View Details
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Notices Section -->
<div id="noticeSection" class="content-section">
<div class="content-card">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3 class="mb-0">
<i class="fas fa-bullhorn me-2"></i> All Notices
</h3>
</div>
<div class="row">
{% if notices %}
{% for notice in notices %}
<div class="col-md-6 mb-4">
<div class="card h-100">
{% if notice.image %}
<img src="{{ notice.image.url }}" class="card-img-top" alt="{{ notice.title }}">
{% endif %}
<div class="card-body">
<h5 class="card-title">{{ notice.title }}</h5>
<p class="card-text">{{ notice.message }}</p>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{ notice.created_at|date:"M d, Y" }}</small>
{% if notice.file %}
<a href="{{ notice.file.url }}" class="btn btn-sm btn-primary" target="_blank">
<i class="fas fa-download me-1"></i>Download
</a>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="col-12">
<div class="text-center py-5">
<i class="fas fa-bullhorn text-muted mb-3" style="font-size: 3rem;"></i>
<p class="text-muted mb-0">No notices available</p>
</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Attendance Section -->
<div id="attendanceSection" class="content-section" style="display: none;">
<div class="content-card">
<h3 class="text-xl font-semibold mb-4">
<i class="fas fa-clipboard-check me-2"></i> Attendance Records
</h3>
<!-- Attendance Summary Cards -->
<div class="row mb-4">
{% for student_info in student_data %}
<div class="col-md-6 col-lg-4 mb-3">
<div class="summary-card h-100">
<div class="card-header">
<h5 class="card-title mb-0 small">
<i class="fas fa-user me-1"></i> {{ student_info.student.name }}
</h5>
</div>
<div class="card-body p-2">
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<span class="d-block text-muted small">Days Attended</span>
<h3>{{ student_info.student.attendance_records.all|filter_attended|length }}</h3>
</div>
<div class="text-end">
<span class="d-block text-muted small">Attendance Rate</span>
{% with attended_classes=student_info.student.attendance_records.all|filter_attended|length %}
{% if student_info.student.course.duration_type == 'Semester' %}
{% with total_period_days=180 %}
{% with attendance_rate=attended_classes|div:total_period_days|multiply:100 %}
<h3 class="text-success">{{ attendance_rate|floatformat:1 }}%</h3>
<div class="d-flex justify-content-between mb-1">
<div><small>0%</small></div>
<div><small>100%</small></div>
</div>
<div class="progress" style="height: 8px; border-radius: 4px;">
<div class="progress-bar bg-success"
role="progressbar"
style="width: {{ attendance_rate }}%"
aria-valuenow="{{ attendance_rate }}"
aria-valuemin="0"
aria-valuemax="100"></div>
</div>
<small class="text-muted d-block mt-1">Minimum required: 75%</small>
{% endwith %}
{% endwith %}
{% else %}
{% with total_period_days=365 %}
{% with attendance_rate=attended_classes|div:total_period_days|multiply:100 %}
<h3 class="text-success">{{ attendance_rate|floatformat:1 }}%</h3>
<div class="d-flex justify-content-between mb-1">
<div><small>0%</small></div>
<div><small>100%</small></div>
</div>
<div class="progress" style="height: 8px; border-radius: 4px;">
<div class="progress-bar bg-success"
role="progressbar"
style="width: {{ attendance_rate }}%"
aria-valuenow="{{ attendance_rate }}"
aria-valuemin="0"
aria-valuemax="100"></div>
</div>
<small class="text-muted d-block mt-1">Minimum required: 75%</small>
{% endwith %}
{% endwith %}
{% endif %}
{% endwith %}
</div>
</div>
<div class="d-flex justify-content-between mb-2">
<small class="mb-0">Present Today</small>
<span class="badge {% if student_info.student.is_present_today %}bg-success{% else %}bg-danger{% endif %} p-2">
{% if student_info.student.is_present_today %}Present{% else %}Absent{% endif %}
</span>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<!-- Attendance Records Table -->
<div class="table-responsive">
<table class="table table-responsive table-hover">
<thead>
<tr>
<th>Student</th>
<th>Date</th>
<th>Subject</th>
<th>Teacher</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for student_info in student_data %}
{% for record in student_info.student.attendance_records.all|slice:":10" %}
<tr>
<td>{{ student_info.student.name }}</td>
<td>{{ record.attendance.date|date:"M d, Y" }}</td>
<td>{{ record.attendance.routine.subject.name }}</td>
<td>{{ record.attendance.teacher.name }}</td>
<td>
<span class="status-badge {% if record.student_attend %}bg-success{% else %}bg-danger{% endif %}">
{% if record.student_attend %}Present{% else %}Absent{% endif %}
</span>
</td>
</tr>
{% empty %}
<tr>
<td colspan="5" class="text-center">No attendance records found for {{ student_info.student.name }}.</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<!-- Routine Section -->
<div id="routineSection" class="content-section" style="display: none;">
<div class="content-card">
<h3 class="text-xl font-semibold mb-4">
<i class="fas fa-calendar me-2"></i> Class Routines
</h3>
<!-- Student Selection Tabs -->
<ul class="nav nav-tabs mb-4" id="studentRoutineTabs" role="tablist">
{% for student_info in student_data %}
<li class="nav-item" role="presentation">
<button class="nav-link {% if forloop.first %}active{% endif %}"
id="student-{{ student_info.student.id }}-tab"
data-bs-toggle="tab"
data-bs-target="#student-{{ student_info.student.id }}"
type="button"
role="tab"
aria-controls="student-{{ student_info.student.id }}"
aria-selected="{% if forloop.first %}true{% else %}false{% endif %}">
{{ student_info.student.name }}
</button>
</li>
{% endfor %}
</ul>
<!-- Student Routine Content -->
<div class="tab-content" id="studentRoutineContent">
{% for student_info in student_data %}
<div class="tab-pane fade {% if forloop.first %}show active{% endif %}"
id="student-{{ student_info.student.id }}"
role="tabpanel"
aria-labelledby="student-{{ student_info.student.id }}-tab">
<div class="mb-3">
<h4 class="mb-2">
<i class="fas fa-user me-2"></i> {{ student_info.student.name }}'s Schedule
</h4>
<p class="text-muted mb-3">
{% if student_info.course_name %}
{{ student_info.course_name }} -
{% if student_info.course_duration_type == 'Semester' %}
Semester {{ student_info.current_period }}
{% else %}
Year {{ student_info.current_period }}
{% endif %}
{% else %}
No course assigned
{% endif %}
</p>
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>Time</th>
<th>Subject</th>
<th>Code</th>
<th>Teacher</th>
</tr>
</thead>
<tbody>
{% if student_info.current_period_routines %}
{% for routine in student_info.current_period_routines %}
<tr>
<td>{{ routine.start_time|time:"h:i A" }} - {{ routine.end_time|time:"h:i A" }}</td>
<td>{{ routine.subject.name }}</td>
<td>{{ routine.subject.code|default:"-" }}</td>
<td>{{ routine.teacher.name }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="4" class="text-center py-4">
<div class="empty-state">
<i class="fas fa-calendar-times mb-2"></i>
<p class="mb-0">No routine available for {{ student_info.student.name }}.</p>
</div>
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<!-- Feedback Section -->
<div id="feedbackSection" class="content-section" style="display: none;">
<div class="content-card">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3 class="mb-0">
<i class="fas fa-comments me-2"></i> Feedback
</h3>
<button class="btn btn-primary" onclick="openParentFeedbackModal()">
<i class="fas fa-plus me-2"></i> Give Feedback
</button>
</div>
<div class="row">
<!-- Teacher Feedback -->
<div class="col-md-6 mb-4">
<h4 class="mb-3">Teacher Feedback</h4>
{% if recent_feedback %}
<div class="feedback-list">
{% for feedback in recent_feedback %}
<div class="feedback-card">
<div class="feedback-header">
<div class="d-flex justify-content-between align-items-center w-100">
<div>
<h5 class="mb-1">{{ feedback.teacher.name }}</h5>
<small class="text-muted">For {{ feedback.student.name }}</small>
</div>
<div class="rating-stars">
{% for i in "12345"|make_list %}
{% if forloop.counter <= feedback.rating %}
<i class="fas fa-star text-warning"></i>
{% else %}
<i class="far fa-star text-warning"></i>
{% endif %}
{% endfor %}
</div>
</div>
</div>
<div class="feedback-message mt-3">
<p>{{ feedback.feedback_text }}</p>
</div>
<div class="feedback-footer mt-2">
<small class="text-muted">{{ feedback.created_at|timesince }} ago</small>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty-state">
<i class="fas fa-comments"></i>
<p>No teacher feedback submitted yet.</p>
</div>
{% endif %}
</div>
<!-- Institute Feedback -->
<div class="col-md-6 mb-4">
<h4 class="mb-3">Institute Feedback</h4>
{% if recent_institute_feedback %}
<div class="feedback-list">
{% for feedback in recent_institute_feedback %}
<div class="feedback-card">
<div class="feedback-header">
<div class="d-flex justify-content-between align-items-center w-100">
<div>
<h5 class="mb-1">{{ feedback.feedback_type }}</h5>
<small class="text-muted">For {{ feedback.student.name }}</small>
</div>
<div class="rating-stars">
{% for i in "12345"|make_list %}
{% if forloop.counter <= feedback.rating %}
<i class="fas fa-star text-warning"></i>
{% else %}
<i class="far fa-star text-warning"></i>
{% endif %}
{% endfor %}
</div>
</div>
</div>
<div class="feedback-message mt-3">
<p>{{ feedback.feedback_text }}</p>
</div>
<div class="feedback-footer mt-2">
<small class="text-muted">{{ feedback.created_at|timesince }} ago</small>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty-state">
<i class="fas fa-building"></i>
<p>No institute feedback submitted yet.</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Subjects Section -->
<div id="subjectsSection" class="content-section" style="display: none;">
<div class="content-card">
<h3 class="text-xl font-semibold mb-4">
<i class="fas fa-book me-2"></i> Subjects
</h3>
<!-- Student Selection Tabs -->
<ul class="nav nav-tabs mb-4" id="studentSubjectTabs" role="tablist">
{% for student_info in student_data %}
<li class="nav-item" role="presentation">
<button class="nav-link {% if forloop.first %}active{% endif %}"
id="subject-student-{{ student_info.student.id }}-tab"
data-bs-toggle="tab"
data-bs-target="#subject-student-{{ student_info.student.id }}"
type="button"
role="tab"
aria-controls="subject-student-{{ student_info.student.id }}"
aria-selected="{% if forloop.first %}true{% else %}false{% endif %}">
{{ student_info.student.name }}
</button>
</li>
{% endfor %}
</ul>
<!-- Student Subjects Content -->
<div class="tab-content" id="studentSubjectContent">
{% for student_info in student_data %}
<div class="tab-pane fade {% if forloop.first %}show active{% endif %}"
id="subject-student-{{ student_info.student.id }}"
role="tabpanel"
aria-labelledby="subject-student-{{ student_info.student.id }}-tab">
<div class="mb-3">
<h4 class="mb-2">
<i class="fas fa-user me-2"></i> {{ student_info.student.name }}'s Subjects
</h4>
<p class="text-muted mb-3">
{% if student_info.course_name %}
{{ student_info.course_name }} -
{% if student_info.course_duration_type == 'Semester' %}
Semester {{ student_info.current_period }}
{% else %}
Year {{ student_info.current_period }}
{% endif %}
{% else %}
No course assigned
{% endif %}
</p>
{% if student_info.current_subjects %}
<div class="row g-3">
{% for subject in student_info.current_subjects %}
<div class="col-md-6 col-lg-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body">
<h5 class="card-title">{{ subject.name }}</h5>
<p class="card-text">
<small class="text-muted d-block">Code: {{ subject.code|default:"Not assigned" }}</small>
</p>
{% with subject_routine=student_info.current_period_routines|filter_by_subject:subject %}
{% if subject_routine %}
<p class="mb-2 text-muted">
<i class="fas fa-clock me-2"></i>
{{ subject_routine.start_time|time:"h:i A" }} - {{ subject_routine.end_time|time:"h:i A" }}
</p>
<p class="mb-0">
<i class="fas fa-chalkboard-teacher me-2"></i>
{{ subject_routine.teacher.name }}
</p>
{% endif %}
{% endwith %}
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty-state">
<i class="fas fa-book mb-2"></i>
<p class="mb-0">No subjects available for {{ student_info.student.name }}.</p>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<!-- Leave Requests Section -->
<div id="leaveSection" class="content-section" style="display: none;">
<div class="content-card">
<h3 class="text-xl font-semibold mb-4">
<i class="fas fa-calendar-minus me-2"></i> Leave Requests History
</h3>
<!-- Student Selection Tabs -->
<ul class="nav nav-tabs mb-4" id="studentLeaveTabs" role="tablist">
{% for student_info in student_data %}
<li class="nav-item" role="presentation">
<button class="nav-link {% if forloop.first %}active{% endif %}"
id="leave-student-{{ student_info.student.id }}-tab"
data-bs-toggle="tab"
data-bs-target="#leave-student-{{ student_info.student.id }}"
type="button"
role="tab"
aria-controls="leave-student-{{ student_info.student.id }}"
aria-selected="{% if forloop.first %}true{% else %}false{% endif %}">
{{ student_info.student.name }}
</button>
</li>
{% endfor %}
</ul>
<!-- Student Leave Requests Content -->
<div class="tab-content" id="studentLeaveContent">
{% for student_info in student_data %}
<div class="tab-pane fade {% if forloop.first %}show active{% endif %}"
id="leave-student-{{ student_info.student.id }}"
role="tabpanel"
aria-labelledby="leave-student-{{ student_info.student.id }}-tab">
<div class="mb-3">
<h4 class="mb-2">
<i class="fas fa-user me-2"></i> {{ student_info.student.name }}'s Leave History
</h4>
{% with student_leaves=student_info.student.leave_requests.all %}
{% if student_leaves %}
<div class="table-responsive">
<table class="table table-hover table-responsive">
<thead class="table-light">
<tr>
<th>Applied On</th>
<th>Start Date</th>
<th>End Date</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for leave in student_leaves %}
<tr>
<td>{{ leave.created_at|date:"M d, Y" }}</td>
<td>{{ leave.start_date|date:"M d, Y" }}</td>
<td>{{ leave.end_date|date:"M d, Y" }}</td>
<td>
<span class="badge {% if leave.status == 1 %}bg-success{% elif leave.status == 2 %}bg-danger{% else %}bg-warning{% endif %}">
{% if leave.status == 1 %}Approved{% elif leave.status == 2 %}Rejected{% else %}Pending{% endif %}
</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="empty-state">
<i class="fas fa-calendar-times mb-2"></i>
<p class="mb-0">No leave requests found for {{ student_info.student.name }}.</p>
</div>
{% endif %}
{% endwith %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<!-- Profile Section -->
<div id="profileSection" class="content-section" style="display: none;">
<div class="content-card">
<h3 class="text-xl font-semibold mb-4">
<i class="fas fa-user-circle me-2"></i> My Profile
</h3>
<div class="row">
<!-- Profile Picture and Basic Info -->
<div class="col-md-4 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<div class="profile-picture-container profile-lg mx-auto mb-3">
{% if parent.image %}
<img src="{{ parent.image.url }}" alt="{{ parent.name }}" class="profile-picture rounded-circle">
{% else %}
<img src="{% static 'img/user.png' %}" alt="Default User" class="profile-picture rounded-circle">
{% endif %}
</div>
<h4 class="mb-1">{{ parent.name }}</h4>
<p class="text-muted mb-3">
<i class="fas fa-user-friends me-1"></i> Parent
</p>
<div class="d-grid gap-2">
<button class="btn btn-primary" onclick="openProfileModal()">
<i class="fas fa-camera me-1"></i> Update Photo
</button>
<button class="btn btn-outline-primary" onclick="openPasswordModal()">
<i class="fas fa-key me-1"></i> Change Password
</button>
</div>
</div>
</div>
</div>
<!-- Personal Information -->
<div class="col-md-8 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-header bg-light py-2">
<h5 class="card-title mb-0"><i class="fas fa-info-circle me-2"></i>Personal Information</h5>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-6">
<p class="mb-1 text-muted">Name</p>
<p class="mb-3">{{ parent.name }}</p>
</div>
<div class="col-md-6">
<p class="mb-1 text-muted">Phone</p>
<p class="mb-3">{{ parent.phone }}</p>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<p class="mb-1 text-muted">Email</p>
<p class="mb-3">{{ parent.email|default:"Not provided" }}</p>
</div>
<div class="col-md-6">
<p class="mb-1 text-muted">Address</p>
<p class="mb-3">{{ parent.address|default:"Not provided" }}</p>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<p class="mb-1 text-muted">Account ID</p>
<p class="mb-3">{{ parent.id }}</p>
</div>
<div class="col-md-6">
<p class="mb-1 text-muted">Account Status</p>
<p class="mb-3">
<span class="badge {% if parent.is_active %}bg-success{% else %}bg-danger{% endif %}">
{% if parent.is_active %}Active{% else %}Inactive{% endif %}
</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- My Children Section -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-light py-2">
<h5 class="card-title mb-0"><i class="fas fa-child me-2"></i>My Children</h5>
</div>
<div class="card-body">
{% if parent.students.all %}
<div class="table-responsive">
<table class="table table-hover table-responsive">
<thead>
<tr>
<th>Name</th>
<th>Course</th>
<th>Current Period</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for student in parent.students.all %}
<tr data-student-id="{{ student.id }}">
<td>
<div class="d-flex align-items-center">
{% if student.image %}
<img src="{{ student.image.url }}" alt="{{ student.name }}" class="rounded-circle me-2" style="width: 32px; height: 32px;">
{% else %}
<div class="student-avatar me-2">
<i class="fas fa-user"></i>
</div>
{% endif %}
{{ student.name }}
</div>
</td>
<td>{{ student.course.name|default:"Not assigned" }}</td>
<td>
{% if student.course %}
{% if student.course.duration_type == 'Semester' %}
Semester {{ student.current_period }}
{% else %}
Year {{ student.current_period }}
{% endif %}
{% else %}
-
{% endif %}
</td>
<td>
<span class="badge {% if student.status == 'Active' %}bg-success{% elif student.status == 'Leave' %}bg-warning{% else %}bg-secondary{% endif %}">
{{ student.status }}
</span>
</td>
<td>
<button class="badge bg-primary border-0" onclick="viewStudentDetails({{ student.id }})">
<i class="fas fa-eye me-1"></i> View Details
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="empty-state">
<i class="fas fa-users mb-2"></i>
<p class="mb-0">No children registered under your account.</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Meetings Section -->
<div id="meetingsSection" class="content-section" style="display: none;">
<div class="content-card">
<h3 class="text-xl font-semibold mb-4">
<i class="fas fa-calendar-check me-2"></i> Parent-Teacher Meetings
</h3>
{% if meetings %}
<div class="table-responsive">
<table class="table table-hover table-responsive">
<thead class="table-light">
<tr>
<th>Date</th>
<th>Time</th>
<th>Duration</th>
<th>Type</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for meeting in meetings %}
<tr>
<td>{{ meeting.meeting_date|date:"M d, Y" }}</td>
<td>{{ meeting.meeting_time|time:"h:i A" }}</td>
<td>{{ meeting.duration }} minutes</td>
<td>
{% if meeting.is_online %}
<span class="badge bg-info">Online</span>
{% if meeting.meeting_link %}
<a href="{{ meeting.meeting_link }}" target="_blank" class="ms-1">
<i class="fas fa-link"></i>
</a>
{% endif %}
{% else %}
<span class="badge bg-secondary">In-person</span>
{% endif %}
</td>
<td>
<span class="badge {% if meeting.status == 'scheduled' %}bg-primary{% elif meeting.status == 'completed' %}bg-success{% elif meeting.status == 'cancelled' %}bg-danger{% else %}bg-warning{% endif %}">
{{ meeting.get_status_display }}
</span>
</td>
<td>
{% if meeting.status == 'completed' %}
<button class="badge bg-success border-0" onclick="viewMeetingNotes({{ meeting.id }})">
<i class="fas fa-sticky-note me-1"></i> View Notes
</button>
{% elif meeting.status == 'cancelled' %}
<button class="badge bg-danger border-0" onclick="viewCancellationReason({{ meeting.id }})">
<i class="fas fa-times-circle me-1"></i> View Reason
</button>
{% endif %}
{% if meeting.notes %}
<button class="badge bg-info border-0 ms-1" onclick="viewMeetingNotes({{ meeting.id }})">
<i class="fas fa-sticky-note me-1"></i> Notes
</button>
{% endif %}
{% if meeting.agenda %}
<button class="badge bg-primary border-0 ms-1" onclick="viewMeetingAgenda({{ meeting.id }})">
<i class="fas fa-clipboard-list me-1"></i> Agenda
</button>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="empty-state">
<i class="fas fa-calendar-times mb-2"></i>
<p class="mb-0">No meetings found.</p>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Common Modals -->
{% include 'shared/common_modals.html' with user=parent %}
<!-- Parent-specific Modals -->
{% include 'parent/modals/feedback_modal.html' %}
{% include 'parent/modals/meeting_notes_modal.html' %}
{% include 'parent/modals/meeting_agenda_modal.html' %}
{% include 'parent/modals/cancellation_reason_modal.html' %}
{% include 'parent/modals/student_details_modal.html' %}
<!-- Bottom Navigation -->
{% include 'shared/bottom_nav.html' with user=parent %}
<!-- Section Navigation Script -->
<script>
function showSection(sectionId) {
// Hide all sections
document.querySelectorAll('.content-section').forEach(section => {
section.style.display = 'none';
});
// Show selected section
const targetSection = document.getElementById(sectionId);
if (targetSection) {
targetSection.style.display = 'block';
}
// Update active button
document.querySelectorAll('.nav-btn, .nav-item').forEach(btn => {
btn.classList.remove('active');
if (btn.getAttribute('onclick')?.includes(sectionId) ||
btn.getAttribute('data-section') === sectionId.replace('Section', '')) {
btn.classList.add('active');
}
});
}
// Student detail view function
function viewStudentDetails(studentId) {
console.log('DEBUG: viewStudentDetails called with studentId:', studentId);
// Show loading state
const modal = document.getElementById('studentDetailsModal');
const errorDiv = document.getElementById('studentDetailsError');
const loadingDiv = document.getElementById('studentDetailsLoading');
const contentDiv = document.getElementById('studentDetailsContent');
// Reset and show modal with loading state
errorDiv.style.display = 'none';
loadingDiv.style.display = 'block';
contentDiv.style.display = 'none';
modal.style.display = 'block';
document.body.style.overflow = 'hidden';
// Fetch student details
fetch(`/app/api/students/${studentId}/details/`)
.then(response => {
if (!response.ok) {
if (response.status === 403) {
throw new Error('You are not authorized to view this student');
} else if (response.status === 404) {
throw new Error('Student not found');
}
throw new Error('Failed to load student details');
}
return response.json();
})
.then(data => {
// Hide loading, show content
loadingDiv.style.display = 'none';
contentDiv.style.display = 'block';
// Update student details
document.getElementById('studentName').textContent = data.name || 'N/A';
document.getElementById('studentId').textContent = data.id || 'N/A';
document.getElementById('studentCourse').textContent = data.course_name || 'Not assigned';
// Set status with badge
let statusBadge = `<span class="badge `;
if (data.status === 'Active') {
statusBadge += `bg-success">Active</span>`;
} else if (data.status === 'Leave') {
statusBadge += `bg-warning">Leave</span>`;
} else {
statusBadge += `bg-secondary">${data.status || 'Unknown'}</span>`;
}
document.getElementById('studentStatusBadge').innerHTML = statusBadge;
// Set period
document.getElementById('studentPeriod').textContent = data.current_period
? `Period ${data.current_period}`
: 'Not assigned';
// Handle student image
if (data.image_url) {
document.getElementById('studentImage').innerHTML = `<img src="${data.image_url}" alt="${data.name}" style="width: 100%; height: 100%; object-fit: cover;">`;
} else {
document.getElementById('studentImage').innerHTML = `<i class="fas fa-user fa-2x text-secondary"></i>`;
}
// Set contact info
document.getElementById('studentEmail').textContent = data.email || 'Not provided';
document.getElementById('studentPhone').textContent = data.phone || 'Not provided';
document.getElementById('studentAddress').textContent = data.address || 'Not provided';
// Set attendance
if (data.attendance_rate) {
document.getElementById('studentAttendance').innerHTML = `
<div class="d-flex align-items-center">
<div class="progress flex-grow-1 me-2" style="height: 8px;">
<div class="progress-bar ${data.attendance_rate.rate < 75 ? 'bg-danger' : 'bg-success'}"
role="progressbar"
style="width: ${data.attendance_rate.rate}%">
</div>
</div>
<span class="text-nowrap">${data.attendance_rate.formatted}</span>
</div>
`;
} else {
document.getElementById('studentAttendance').textContent = 'No data available';
}
// Set course timeline information
document.getElementById('studentCourseName').textContent = data.course_name || 'Not available';
document.getElementById('studentCourseCode').textContent = data.course_code || 'Not available';
document.getElementById('studentCourseStatus').textContent = data.course_status || 'Not available';
document.getElementById('studentCurrentPeriod').textContent = data.current_period || 'Not available';
document.getElementById('studentCourseDescription').textContent = data.course_description || 'No description available';
document.getElementById('studentPeriodEndDate').textContent = data.expected_end_date || 'Not available';
document.getElementById('studentCourseEndDate').textContent = data.course_end_date || 'Not available';
document.getElementById('studentProgressBar').style.width = `${data.progress}%`;
})
.catch(error => {
console.error('Error fetching student details:', error);
loadingDiv.style.display = 'none';
errorDiv.style.display = 'block';
errorDiv.textContent = error.message || 'Failed to load student details. Please try again.';
contentDiv.style.display = 'none';
});
}
function closeStudentDetailsModal() {
const modal = document.getElementById('studentDetailsModal');
modal.style.display = 'none';
document.body.style.overflow = '';
}
// Add escape key handler for student details modal
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
const studentDetailsModal = document.getElementById('studentDetailsModal');
if (studentDetailsModal.style.display === 'block') {
closeStudentDetailsModal();
}
}
});
// Meeting-related functions
function viewMeetingNotes(meetingId) {
fetch(`/app/api/meetings/${meetingId}/notes/`)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.statusText);
}
return response.json();
})
.then(data => {
document.getElementById('meetingNotesContent').innerHTML = data.notes || 'No notes available';
document.getElementById('meetingNotesModal').style.display = 'block';
document.body.style.overflow = 'hidden';
})
.catch(error => {
console.error('Error fetching meeting notes:', error);
alert('Error loading meeting notes. Please try again.');
});
}
function closeMeetingNotesModal() {
document.getElementById('meetingNotesModal').style.display = 'none';
document.body.style.overflow = '';
}
function viewMeetingAgenda(meetingId) {
fetch(`/app/api/meetings/${meetingId}/agenda/`)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.statusText);
}
return response.json();
})
.then(data => {
document.getElementById('meetingAgendaContent').innerHTML = data.agenda || 'No agenda available';
document.getElementById('meetingAgendaModal').style.display = 'block';
document.body.style.overflow = 'hidden';
})
.catch(error => {
console.error('Error fetching meeting agenda:', error);
alert('Error loading meeting agenda. Please try again.');
});
}
function closeMeetingAgendaModal() {
document.getElementById('meetingAgendaModal').style.display = 'none';
document.body.style.overflow = '';
}
function viewCancellationReason(meetingId) {
fetch(`/app/api/meetings/${meetingId}/cancellation-reason/`)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.statusText);
}
return response.json();
})
.then(data => {
document.getElementById('cancellationReasonContent').innerHTML = data.reason || 'No reason provided';
document.getElementById('cancellationReasonModal').style.display = 'block';
document.body.style.overflow = 'hidden';
})
.catch(error => {
console.error('Error fetching cancellation reason:', error);
alert('Error loading cancellation reason. Please try again.');
});
}
function closeCancellationReasonModal() {
document.getElementById('cancellationReasonModal').style.display = 'none';
document.body.style.overflow = '';
}
// Add event listeners for closing modals with Escape key
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
const meetingNotesModal = document.getElementById('meetingNotesModal');
const meetingAgendaModal = document.getElementById('meetingAgendaModal');
const cancellationReasonModal = document.getElementById('cancellationReasonModal');
if (meetingNotesModal.style.display === 'block') {
closeMeetingNotesModal();
}
if (meetingAgendaModal.style.display === 'block') {
closeMeetingAgendaModal();
}
if (cancellationReasonModal.style.display === 'block') {
closeCancellationReasonModal();
}
}
});
</script>
<!-- Navigation Button Styles -->
<style type="text/css">
.nav-buttons {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
flex-wrap: wrap;
}
.nav-btn {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
background: #f8f9fa;
color: #6c757d;
font-weight: 500;
transition: all 0.2s ease;
}
.nav-btn:hover {
background: #e9ecef;
color: #495057;
}
.nav-btn.active {
background: var(--primary);
color: white;
}
.nav-btn i {
font-size: 1.1rem;
}
@media (max-width: 768px) {
.nav-buttons {
justify-content: center;
}
.nav-btn {
padding: 0.5rem 1rem;
}
.nav-btn span {
display: none;
}
.nav-btn i {
font-size: 1.2rem;
margin: 0;
}
}
</style>
{% endblock %}
{% block extrascripts %}
{{ block.super }}
<script>
// Initialize Firebase and request notification permission when the page loads
document.addEventListener('DOMContentLoaded', function() {
// Call getDeviceToken to initialize Firebase and request notification permission
if (typeof getDeviceToken === 'function') {
getDeviceToken().catch(error => {
console.error('Error initializing Firebase:', error);
});
}
});
</script>
{% endblock %}