Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9b7d8af32 | ||
|
|
53b2eca493 | ||
|
|
3d54aeb8f0 | ||
|
|
7acb928eca | ||
|
|
4d076f05c2 | ||
|
|
1839023496 | ||
|
|
93f530e4f6 | ||
|
|
e15fa31a20 | ||
|
|
082d14fa79 | ||
|
|
a2059511fc | ||
|
|
acd454b06b | ||
|
|
4359789531 |
32
activities.php
Normal file
32
activities.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
//header('Location: login.php');
|
||||
//exit();
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Activities</title>
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Activities</h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="teacher_dashboard.php">Dashboard</a></li>
|
||||
<li><a href="logout.php">Logout</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<h2>Activity Management</h2>
|
||||
<p>This page will contain student activity information.</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
33
admin_dashboard.php
Normal file
33
admin_dashboard.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['role_name'] !== 'admin') {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Dashboard</title>
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Admin Dashboard</h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="users.php">Manage Users</a></li>
|
||||
<li><a href="roles.php">Manage Roles</a></li>
|
||||
<li><a href="logout.php">Logout</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<h2>Welcome, Admin!</h2>
|
||||
<p>This is your dashboard. You can manage users and roles from here.</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
74
assets/css/custom.css
Normal file
74
assets/css/custom.css
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
:root {
|
||||
--primary-color: #4a90e2;
|
||||
--secondary-color: #50e3c2;
|
||||
--background-color: #f9f9f9;
|
||||
--surface-color: #ffffff;
|
||||
--text-color: #333333;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Vazirmatn', sans-serif;
|
||||
direction: rtl;
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
|
||||
color: white;
|
||||
padding: 100px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background-color: var(--surface-color);
|
||||
border-radius: 8px;
|
||||
padding: 30px;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.feature-card i {
|
||||
font-size: 3rem;
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-color);
|
||||
border-color: var(--primary-color);
|
||||
border-radius: 8px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #357ABD;
|
||||
border-color: #357ABD;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background-color: var(--surface-color);
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
#loginModal .modal-content {
|
||||
border-radius: 8px;
|
||||
}
|
||||
13
assets/js/main.js
Normal file
13
assets/js/main.js
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Smooth scroll for hero button
|
||||
const heroBtn = document.querySelector('.hero .btn');
|
||||
if (heroBtn) {
|
||||
heroBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
document.querySelector('#features').scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
216
attendance.php
Normal file
216
attendance.php
Normal file
@ -0,0 +1,216 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
//header('Location: login.php');
|
||||
//exit();
|
||||
}
|
||||
|
||||
$role_name = $_SESSION['role_name'];
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
function get_students() {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT u.id, u.first_name, u.last_name FROM users u JOIN roles r ON u.role_id = r.id WHERE r.role_name = 'student'");
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
function get_children_for_parent($parent_id) {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT u.id, u.first_name, u.last_name FROM users u JOIN parent_child pc ON u.id = pc.child_id WHERE pc.parent_id = ?");
|
||||
$stmt->execute([$parent_id]);
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
function get_student_attendance($student_id) {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT attendance_date, status FROM attendance WHERE student_id = ? ORDER BY attendance_date DESC");
|
||||
$stmt->execute([$student_id]);
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $role_name === 'teacher') {
|
||||
$attendance_date = $_POST['attendance_date'];
|
||||
$students = $_POST['students'];
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("INSERT INTO attendance (student_id, attendance_date, status) VALUES (?, ?, ?)");
|
||||
|
||||
foreach ($students as $student_id => $status) {
|
||||
$stmt->execute([$student_id, $attendance_date, $status]);
|
||||
}
|
||||
$success_message = "Attendance for $attendance_date has been saved.";
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Attendance</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<header class="p-3 mb-3 border-bottom sticky-top bg-light">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-dark text-decoration-none">
|
||||
<span class="fs-4">School Management</span>
|
||||
</a>
|
||||
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
|
||||
<?php if ($role_name === 'teacher'): ?>
|
||||
<li><a href="teacher_dashboard.php" class="nav-link px-2 link-dark">Dashboard</a></li>
|
||||
<li><a href="attendance.php" class="nav-link px-2 link-secondary">Attendance</a></li>
|
||||
<li><a href="exams.php" class="nav-link px-2 link-dark">Exams</a></li>
|
||||
<li><a href="activities.php" class="nav-link px-2 link-dark">Activities</a></li>
|
||||
<?php elseif ($role_name === 'student'): ?>
|
||||
<li><a href="student_dashboard.php" class="nav-link px-2 link-dark">Dashboard</a></li>
|
||||
<li><a href="attendance.php" class="nav-link px-2 link-secondary">Attendance</a></li>
|
||||
<li><a href="exams.php" class="nav-link px-2 link-dark">Exams</a></li>
|
||||
<li><a href="activities.php" class="nav-link px-2 link-dark">Activities</a></li>
|
||||
<?php elseif ($role_name === 'parent'): ?>
|
||||
<li><a href="parent_dashboard.php" class="nav-link px-2 link-dark">Dashboard</a></li>
|
||||
<li><a href="attendance.php" class="nav-link px-2 link-secondary">Attendance</a></li>
|
||||
<li><a href="exams.php" class="nav-link px-2 link-dark">Exams</a></li>
|
||||
<li><a href="activities.php" class="nav-link px-2 link-dark">Activities</a></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
<div class="text-end">
|
||||
<a href="logout.php" class="btn btn-outline-primary">Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main class="container py-5">
|
||||
<h1>Attendance</h1>
|
||||
|
||||
<?php if (isset($success_message)): ?>
|
||||
<div class="alert alert-success"><?php echo $success_message; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($role_name === 'teacher'): ?>
|
||||
<h2>Take Attendance</h2>
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="attendance_date" class="form-label">Date</label>
|
||||
<input type="date" class="form-control" id="attendance_date" name="attendance_date" value="<?php echo date('Y-m-d'); ?>" required>
|
||||
</div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Student Name</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$students = get_students();
|
||||
foreach ($students as $student):
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($student['first_name'] . ' ' . $student['last_name']); ?></td>
|
||||
<td>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="radio" name="students[<?php echo $student['id']; ?>]" id="present_<?php echo $student['id']; ?>" value="present" checked>
|
||||
<label class="form-check-label" for="present_<?php echo $student['id']; ?>">Present</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="radio" name="students[<?php echo $student['id']; ?>]" id="absent_<?php echo $student['id']; ?>" value="absent">
|
||||
<label class="form-check-label" for="absent_<?php echo $student['id']; ?>">Absent</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="radio" name="students[<?php echo $student['id']; ?>]" id="late_<?php echo $student['id']; ?>" value="late">
|
||||
<label class="form-check-label" for="late_<?php echo $student['id']; ?>">Late</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="submit" class="btn btn-primary">Submit Attendance</button>
|
||||
</form>
|
||||
<?php elseif ($role_name === 'student'): ?>
|
||||
<h2>My Attendance</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$attendance_records = get_student_attendance($user_id);
|
||||
foreach ($attendance_records as $record):
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($record['attendance_date']); ?></td>
|
||||
<td><?php echo htmlspecialchars($record['status']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php elseif ($role_name === 'parent'): ?>
|
||||
<h2>My Child's Attendance</h2>
|
||||
<?php
|
||||
$children = get_children_for_parent($user_id);
|
||||
if (count($children) > 0):
|
||||
?>
|
||||
<form method="GET" class="mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<label for="child_id" class="form-label">Select Child</label>
|
||||
<select class="form-select" id="child_id" name="child_id" onchange="this.form.submit()">
|
||||
<option value="">Select a child</option>
|
||||
<?php foreach ($children as $child): ?>
|
||||
<option value="<?php echo $child['id']; ?>" <?php echo (isset($_GET['child_id']) && $_GET['child_id'] == $child['id']) ? 'selected' : ''; ?>><?php echo htmlspecialchars($child['first_name'] . ' ' . $child['last_name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php if (isset($_GET['child_id'])):
|
||||
$child_id = $_GET['child_id'];
|
||||
// Make sure the selected child belongs to the parent
|
||||
$is_child_of_parent = false;
|
||||
foreach ($children as $child) {
|
||||
if ($child['id'] == $child_id) {
|
||||
$is_child_of_parent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($is_child_of_parent):
|
||||
?>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$attendance_records = get_student_attendance($child_id);
|
||||
foreach ($attendance_records as $record):
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($record['attendance_date']); ?></td>
|
||||
<td><?php echo htmlspecialchars($record['status']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-danger">Invalid child selected.</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<p>You have no children linked to your account.</p>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
34
database.sql
Normal file
34
database.sql
Normal file
@ -0,0 +1,34 @@
|
||||
DROP TABLE IF EXISTS attendance, parent_child, users, roles;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS roles (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
role_name VARCHAR(255) NOT NULL UNIQUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(255) NOT NULL UNIQUE,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role_id INT,
|
||||
first_name VARCHAR(255),
|
||||
last_name VARCHAR(255),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS attendance (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
student_id INT NOT NULL,
|
||||
attendance_date DATE NOT NULL,
|
||||
status ENUM('present', 'absent', 'late') NOT NULL,
|
||||
FOREIGN KEY (student_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS parent_child (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
parent_id INT NOT NULL,
|
||||
child_id INT NOT NULL,
|
||||
FOREIGN KEY (parent_id) REFERENCES users(id),
|
||||
FOREIGN KEY (child_id) REFERENCES users(id)
|
||||
);
|
||||
21
db/migrate.php
Normal file
21
db/migrate.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
function run_migrations() {
|
||||
$pdo = db();
|
||||
$migrations_dir = __DIR__ . '/migrations';
|
||||
$files = glob($migrations_dir . '/*.sql');
|
||||
|
||||
foreach ($files as $file) {
|
||||
$sql = file_get_contents($file);
|
||||
try {
|
||||
$pdo->exec($sql);
|
||||
echo "Migration from $file executed successfully.\n";
|
||||
} catch (PDOException $e) {
|
||||
echo "Error executing migration from $file: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run_migrations();
|
||||
|
||||
1
db/migrations/000_drop_tables.sql
Normal file
1
db/migrations/000_drop_tables.sql
Normal file
@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS attendance, parent_child, users, roles;
|
||||
4
db/migrations/001_create_roles_table.sql
Normal file
4
db/migrations/001_create_roles_table.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE TABLE IF NOT EXISTS roles (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
role_name VARCHAR(255) NOT NULL UNIQUE
|
||||
);
|
||||
11
db/migrations/002_create_users_table.sql
Normal file
11
db/migrations/002_create_users_table.sql
Normal file
@ -0,0 +1,11 @@
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(255) NOT NULL UNIQUE,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role_id INT,
|
||||
first_name VARCHAR(255),
|
||||
last_name VARCHAR(255),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE SET NULL
|
||||
);
|
||||
7
db/migrations/003_create_attendance_table.sql
Normal file
7
db/migrations/003_create_attendance_table.sql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS attendance (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
student_id INT NOT NULL,
|
||||
attendance_date DATE NOT NULL,
|
||||
status ENUM('present', 'absent', 'late') NOT NULL,
|
||||
FOREIGN KEY (student_id) REFERENCES users(id)
|
||||
);
|
||||
7
db/migrations/004_create_parent_child_table.sql
Normal file
7
db/migrations/004_create_parent_child_table.sql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS parent_child (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
parent_id INT NOT NULL,
|
||||
child_id INT NOT NULL,
|
||||
FOREIGN KEY (parent_id) REFERENCES users(id),
|
||||
FOREIGN KEY (child_id) REFERENCES users(id)
|
||||
);
|
||||
7
db/migrations/005_create_exams_table.sql
Normal file
7
db/migrations/005_create_exams_table.sql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS exams (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
created_by INT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
9
db/migrations/006_create_exam_questions_table.sql
Normal file
9
db/migrations/006_create_exam_questions_table.sql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE TABLE IF NOT EXISTS exam_questions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
exam_id INT NOT NULL,
|
||||
question_text TEXT NOT NULL,
|
||||
question_type ENUM('multiple_choice', 'free_text') NOT NULL,
|
||||
options JSON,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (exam_id) REFERENCES exams(id) ON DELETE CASCADE
|
||||
);
|
||||
12
db/migrations/007_create_student_exams_table.sql
Normal file
12
db/migrations/007_create_student_exams_table.sql
Normal file
@ -0,0 +1,12 @@
|
||||
CREATE TABLE IF NOT EXISTS student_exams (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
exam_id INT NOT NULL,
|
||||
student_id INT NOT NULL,
|
||||
status ENUM('assigned', 'in-progress', 'completed') DEFAULT 'assigned',
|
||||
score INT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (exam_id) REFERENCES exams(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (student_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
UNIQUE KEY (exam_id, student_id)
|
||||
);
|
||||
10
db/migrations/008_create_student_answers_table.sql
Normal file
10
db/migrations/008_create_student_answers_table.sql
Normal file
@ -0,0 +1,10 @@
|
||||
CREATE TABLE IF NOT EXISTS student_answers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
student_exam_id INT NOT NULL,
|
||||
question_id INT NOT NULL,
|
||||
answer_text TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (student_exam_id) REFERENCES student_exams(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (question_id) REFERENCES exam_questions(id) ON DELETE CASCADE,
|
||||
UNIQUE KEY (student_exam_id, question_id)
|
||||
);
|
||||
180
exam_questions.php
Normal file
180
exam_questions.php
Normal file
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$role = $_SESSION['role'];
|
||||
|
||||
if ($role !== 'teacher') {
|
||||
header('Location: ' . $role . '_dashboard.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
if (!isset($_GET['exam_id'])) {
|
||||
header('Location: exams.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$exam_id = $_GET['exam_id'];
|
||||
$pdo = db();
|
||||
|
||||
// Verify the teacher owns the exam
|
||||
$stmt = $pdo->prepare('SELECT * FROM exams WHERE id = ? AND created_by = ?');
|
||||
$stmt->execute([$exam_id, $user_id]);
|
||||
$exam = $stmt->fetch();
|
||||
|
||||
if (!$exam) {
|
||||
echo "Exam not found or you don't have permission to edit it.";
|
||||
exit();
|
||||
}
|
||||
|
||||
// Handle question form submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['question_text'])) {
|
||||
$question_text = trim($_POST['question_text']);
|
||||
$question_type = $_POST['question_type'];
|
||||
$options = null;
|
||||
|
||||
if ($question_type === 'multiple_choice') {
|
||||
$options_raw = trim($_POST['options']);
|
||||
if (!empty($options_raw)) {
|
||||
$options = json_encode(array_map('trim', explode("\n", $options_raw)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($question_text)) {
|
||||
if (isset($_POST['question_id']) && !empty($_POST['question_id'])) {
|
||||
// Update question
|
||||
$stmt = $pdo->prepare('UPDATE exam_questions SET question_text = ?, question_type = ?, options = ? WHERE id = ? AND exam_id = ?');
|
||||
$stmt->execute([$question_text, $question_type, $options, $_POST['question_id'], $exam_id]);
|
||||
} else {
|
||||
// Add new question
|
||||
$stmt = $pdo->prepare('INSERT INTO exam_questions (exam_id, question_text, question_type, options) VALUES (?, ?, ?, ?)');
|
||||
$stmt->execute([$exam_id, $question_text, $question_type, $options]);
|
||||
}
|
||||
}
|
||||
header('Location: exam_questions.php?exam_id=' . $exam_id);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Handle question deletion
|
||||
if (isset($_GET['delete_question'])) {
|
||||
$question_id = $_GET['delete_question'];
|
||||
$stmt = $pdo->prepare('DELETE FROM exam_questions WHERE id = ? AND exam_id = ?');
|
||||
$stmt->execute([$question_id, $exam_id]);
|
||||
header('Location: exam_questions.php?exam_id=' . $exam_id);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Fetch questions for the exam
|
||||
$stmt = $pdo->prepare('SELECT * FROM exam_questions WHERE exam_id = ? ORDER BY created_at ASC');
|
||||
$stmt->execute([$exam_id]);
|
||||
$questions = $stmt->fetchAll();
|
||||
|
||||
// Check if we are editing a question
|
||||
$edit_question = null;
|
||||
if (isset($_GET['edit_question'])) {
|
||||
$stmt = $pdo->prepare('SELECT * FROM exam_questions WHERE id = ? AND exam_id = ?');
|
||||
$stmt->execute([$_GET['edit_question'], $exam_id]);
|
||||
$edit_question = $stmt->fetch();
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Manage Questions for <?php echo htmlspecialchars($exam['name']); ?></title>
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Manage Questions for "<?php echo htmlspecialchars($exam['name']); ?>"</h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="exams.php">Back to Exams</a></li>
|
||||
<li><a href="teacher_dashboard.php">Dashboard</a></li>
|
||||
<li><a href="logout.php">Logout</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<section>
|
||||
<h2><?php echo $edit_question ? 'Edit' : 'Add'; ?> Question</h2>
|
||||
<form action="exam_questions.php?exam_id=<?php echo $exam_id; ?>" method="POST">
|
||||
<?php if ($edit_question): ?>
|
||||
<input type="hidden" name="question_id" value="<?php echo htmlspecialchars($edit_question['id']); ?>">
|
||||
<?php endif; ?>
|
||||
<div>
|
||||
<label for="question_text">Question:</label>
|
||||
<textarea id="question_text" name="question_text" rows="3" required><?php echo $edit_question ? htmlspecialchars($edit_question['question_text']) : ''; ?></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<label for="question_type">Question Type:</label>
|
||||
<select id="question_type" name="question_type">
|
||||
<option value="free_text" <?php echo ($edit_question && $edit_question['question_type'] === 'free_text') ? 'selected' : ''; ?>>Free Text</option>
|
||||
<option value="multiple_choice" <?php echo ($edit_question && $edit_question['question_type'] === 'multiple_choice') ? 'selected' : ''; ?>>Multiple Choice</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="mc_options_container">
|
||||
<label for="options">Options (one per line):</label>
|
||||
<textarea id="options" name="options" rows="5"><?php echo ($edit_question && $edit_question['options']) ? htmlspecialchars(implode("\n", json_decode($edit_question['options']))) : ''; ?></textarea>
|
||||
</div>
|
||||
<button type="submit"><?php echo $edit_question ? 'Update' : 'Add'; ?> Question</button>
|
||||
<?php if ($edit_question): ?>
|
||||
<a href="exam_questions.php?exam_id=<?php echo $exam_id; ?>">Cancel Edit</a>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Questions</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Question</th>
|
||||
<th>Type</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($questions as $question):
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo nl2br(htmlspecialchars($question['question_text'])); ?></td>
|
||||
<td><?php echo htmlspecialchars(str_replace('_', ' ', $question['question_type'])); ?></td>
|
||||
<td>
|
||||
<a href="exam_questions.php?exam_id=<?php echo $exam_id; ?>&edit_question=<?php echo $question['id']; ?>">Edit</a> |
|
||||
<a href="exam_questions.php?exam_id=<?php echo $exam_id; ?>&delete_question=<?php echo $question['id']; ?>" onclick="return confirm('Are you sure you want to delete this question?');">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($questions)):
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="3">No questions have been added to this exam yet.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</main>
|
||||
<script>
|
||||
// Show/hide multiple choice options based on question type selection
|
||||
const questionType = document.getElementById('question_type');
|
||||
const mcOptionsContainer = document.getElementById('mc_options_container');
|
||||
|
||||
function toggleMcOptions() {
|
||||
mcOptionsContainer.style.display = questionType.value === 'multiple_choice' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
toggleMcOptions(); // Initial check
|
||||
questionType.addEventListener('change', toggleMcOptions);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
177
exams.php
Normal file
177
exams.php
Normal file
@ -0,0 +1,177 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$role = $_SESSION['role'];
|
||||
$pdo = db();
|
||||
|
||||
$page_title = 'Exams';
|
||||
$header_links = '<a href="' . $role . '_dashboard.php">Dashboard</a>';
|
||||
|
||||
// Role-based logic
|
||||
if ($role === 'teacher') {
|
||||
$page_title = 'Manage Exams';
|
||||
|
||||
// Handle form submissions for creating/editing exams
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['exam_name'])) {
|
||||
$exam_name = trim($_POST['exam_name']);
|
||||
if (!empty($exam_name)) {
|
||||
if (isset($_POST['exam_id']) && !empty($_POST['exam_id'])) {
|
||||
$stmt = $pdo->prepare('UPDATE exams SET name = ? WHERE id = ? AND created_by = ?');
|
||||
$stmt->execute([$exam_name, $_POST['exam_id'], $user_id]);
|
||||
} else {
|
||||
$stmt = $pdo->prepare('INSERT INTO exams (name, created_by) VALUES (?, ?)');
|
||||
$stmt->execute([$exam_name, $user_id]);
|
||||
}
|
||||
}
|
||||
header('Location: exams.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
// Handle exam deletion
|
||||
if (isset($_GET['delete_exam'])) {
|
||||
$stmt = $pdo->prepare('DELETE FROM exams WHERE id = ? AND created_by = ?');
|
||||
$stmt->execute([$_GET['delete_exam'], $user_id]);
|
||||
header('Location: exams.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
// Fetch exams for the teacher view
|
||||
$stmt = $pdo->prepare('SELECT * FROM exams WHERE created_by = ? ORDER BY created_at DESC');
|
||||
$stmt->execute([$user_id]);
|
||||
$exams = $stmt->fetchAll();
|
||||
|
||||
// Check if we are editing an exam
|
||||
$edit_exam = null;
|
||||
if (isset($_GET['edit_exam'])) {
|
||||
$stmt = $pdo->prepare('SELECT * FROM exams WHERE id = ? AND created_by = ?');
|
||||
$stmt->execute([$_GET['edit_exam'], $user_id]);
|
||||
$edit_exam = $stmt->fetch();
|
||||
}
|
||||
|
||||
} elseif ($role === 'student') {
|
||||
$page_title = 'Your Exams';
|
||||
|
||||
// Fetch assigned exams for the student view
|
||||
$stmt = $pdo->prepare('
|
||||
SELECT e.name, se.status, se.score, se.id as student_exam_id
|
||||
FROM student_exams se
|
||||
JOIN exams e ON se.exam_id = e.id
|
||||
WHERE se.student_id = ?
|
||||
ORDER BY e.created_at DESC
|
||||
');
|
||||
$stmt->execute([$user_id]);
|
||||
$assigned_exams = $stmt->fetchAll();
|
||||
|
||||
} else {
|
||||
// Redirect other roles to their dashboard
|
||||
header('Location: ' . $role . '_dashboard.php');
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo $page_title; ?></title>
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1><?php echo $page_title; ?></h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><?php echo $header_links; ?></li>
|
||||
<li><a href="logout.php">Logout</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<?php if ($role === 'teacher'): ?>
|
||||
<section>
|
||||
<h2><?php echo $edit_exam ? 'Edit' : 'Create'; ?> Exam</h2>
|
||||
<form action="exams.php" method="POST">
|
||||
<?php if ($edit_exam): ?>
|
||||
<input type="hidden" name="exam_id" value="<?php echo htmlspecialchars($edit_exam['id']); ?>">
|
||||
<?php endif; ?>
|
||||
<div>
|
||||
<label for="exam_name">Exam Name:</label>
|
||||
<input type="text" id="exam_name" name="exam_name" value="<?php echo $edit_exam ? htmlspecialchars($edit_exam['name']) : ''; ?>" required>
|
||||
</div>
|
||||
<button type="submit"><?php echo $edit_exam ? 'Update' : 'Create'; ?> Exam</button>
|
||||
<?php if ($edit_exam): ?>
|
||||
<a href="exams.php">Cancel Edit</a>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Your Exams</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Exam Name</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($exams as $exam): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($exam['name']); ?></td>
|
||||
<td>
|
||||
<a href="view_submissions.php?exam_id=<?php echo $exam['id']; ?>">View Submissions</a> |
|
||||
<a href="exams.php?edit_exam=<?php echo $exam['id']; ?>">Edit</a> |
|
||||
<a href="exam_questions.php?exam_id=<?php echo $exam['id']; ?>">Manage Questions</a> |
|
||||
<a href="exams.php?delete_exam=<?php echo $exam['id']; ?>" onclick="return confirm('Are you sure you want to delete this exam?');">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($exams)): ?>
|
||||
<tr><td colspan="2">You have not created any exams yet.</td></tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<?php elseif ($role === 'student'): ?>
|
||||
<section>
|
||||
<h2>Assigned Exams</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Exam Name</th>
|
||||
<th>Status</th>
|
||||
<th>Score</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($assigned_exams as $exam): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($exam['name']); ?></td>
|
||||
<td><?php echo htmlspecialchars(ucfirst($exam['status'])); ?></td>
|
||||
<td><?php echo $exam['score'] !== null ? $exam['score'] . '%' : 'Not graded'; ?></td>
|
||||
<td>
|
||||
<?php if ($exam['status'] === 'assigned' || $exam['status'] === 'in-progress'): ?>
|
||||
<a href="take_exam.php?student_exam_id=<?php echo $exam['student_exam_id']; ?>">Take Exam</a>
|
||||
<?php elseif ($exam['status'] === 'completed'): ?>
|
||||
<a href="view_results.php?student_exam_id=<?php echo $exam['student_exam_id']; ?>">View Results</a>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($assigned_exams)): ?>
|
||||
<tr><td colspan="4">You have no assigned exams.</td></tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
237
index.php
237
index.php
@ -1,150 +1,111 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@ini_set('display_errors', '1');
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
|
||||
$phpVersion = PHP_VERSION;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<?php session_start(); ?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
<?php
|
||||
// Read project preview data from environment
|
||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
?>
|
||||
<?php if ($projectDescription): ?>
|
||||
<!-- Meta description -->
|
||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||
<!-- Open Graph meta tags -->
|
||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<!-- Twitter meta tags -->
|
||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<?php endif; ?>
|
||||
<?php if ($projectImageUrl): ?>
|
||||
<!-- Open Graph image -->
|
||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<!-- Twitter image -->
|
||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<?php endif; ?>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>سیستم مدیریت مدرسه</title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($_SERVER['PROJECT_DESCRIPTION'] ?? 'سیستم جامع مدیریت مدرسه'); ?>">
|
||||
|
||||
<!-- Bootstrap RTL CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||
animation: bg-pan 20s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes bg-pan {
|
||||
0% { background-position: 0% 0%; }
|
||||
100% { background-position: 100% 100%; }
|
||||
}
|
||||
main {
|
||||
padding: 2rem;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-bg-color);
|
||||
border: 1px solid var(--card-border-color);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.loader {
|
||||
margin: 1.25rem auto 1.25rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.hint {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px; height: 1px;
|
||||
padding: 0; margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap; border: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1rem;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
code {
|
||||
background: rgba(0,0,0,0.2);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Feather Icons -->
|
||||
<script src="https://unpkg.com/feather-icons"></script>
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
|
||||
<meta property="og:title" content="School Management System">
|
||||
<meta property="og:description" content="<?php echo htmlspecialchars($_SERVER['PROJECT_DESCRIPTION'] ?? 'A comprehensive school management system.'); ?>">
|
||||
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="p-3 mb-3 border-bottom sticky-top bg-light">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-dark text-decoration-none">
|
||||
<span class="fs-4">مدیریت مدرسه</span>
|
||||
</a>
|
||||
|
||||
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
|
||||
<li><a href="index.php" class="nav-link px-2 link-secondary">خانه</a></li>
|
||||
<li><a href="roles.php" class="nav-link px-2 link-dark">مدیریت نقشها</a></li>
|
||||
<li><a href="users.php" class="nav-link px-2 link-dark">مدیریت کاربران</a></li>
|
||||
<a href="activities.php">Activities</a>
|
||||
<a href="exams.php">Exams</a>
|
||||
<a href="attendance.php">Attendance</a>
|
||||
</ul>
|
||||
|
||||
<div class="text-end">
|
||||
<?php if (isset($_SESSION['user_id'])): ?>
|
||||
<a href="logout.php" class="btn btn-outline-primary">خروج</a>
|
||||
<?php else: ?>
|
||||
<a href="login.php" class="btn btn-primary">ورود</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<h1>سیستم مدیریت یکپارچه مدرسه</h1>
|
||||
<p>راه حلی مدرن برای مدیریت تمام امور مدرسه شما</p>
|
||||
<a href="#features" class="btn btn-light btn-lg">بیشتر بدانید</a>
|
||||
</div>
|
||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
</section>
|
||||
|
||||
<section id="features" class="py-5">
|
||||
<div class="container">
|
||||
<h2 class="text-center mb-5">امکانات سیستم</h2>
|
||||
<div class="row text-center">
|
||||
<div class="col-md-4">
|
||||
<div class="feature-card">
|
||||
<i data-feather="users"></i>
|
||||
<h3>مدیریت دانشآموزان</h3>
|
||||
<p>ثبتنام، اطلاعات تحصیلی و حضور و غیاب.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="feature-card">
|
||||
<i data-feather="briefcase"></i>
|
||||
<h3>مدیریت معلمان</h3>
|
||||
<p>اطلاعات پرسنلی، برنامهریزی درسی و ارتباط با والدین.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="feature-card">
|
||||
<i data-feather="book-open"></i>
|
||||
<h3>مدیریت دورهها</h3>
|
||||
<p>ایجاد و مدیریت کلاسها و واحدهای درسی.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
|
||||
<footer class="footer mt-auto py-3 bg-light">
|
||||
<div class="container">
|
||||
<span class="text-muted">© 2025 سیستم مدیریت مدرسه</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- Custom JS -->
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
<script>
|
||||
feather.replace()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
126
login.php
Normal file
126
login.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
$db = db();
|
||||
|
||||
// Redirect if already logged in
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
header("Location: index.php");
|
||||
exit();
|
||||
}
|
||||
|
||||
$error_message = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$username = $_POST['username'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
if (empty($username) || empty($password)) {
|
||||
$error_message = 'Please enter both username and password.';
|
||||
} else {
|
||||
$stmt = $db->prepare("SELECT id, password, role_id FROM users WHERE username = :username");
|
||||
$stmt->bindParam(':username', $username);
|
||||
$stmt->execute();
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($user && password_verify($password, $user['password'])) {
|
||||
$_SESSION['user_id'] = $user['id'];
|
||||
$_SESSION['username'] = $username;
|
||||
$_SESSION['role_id'] = $user['role_id'];
|
||||
|
||||
// Fetch role name
|
||||
$role_stmt = $db->prepare("SELECT name FROM roles WHERE id = :role_id");
|
||||
$role_stmt->bindParam(':role_id', $user['role_id']);
|
||||
$role_stmt->execute();
|
||||
$role = $role_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$role_name = $role ? $role['name'] : null;
|
||||
$_SESSION['role_name'] = $role_name;
|
||||
|
||||
// Log attendance
|
||||
$login_time = date('Y-m-d H:i:s');
|
||||
$ip_address = $_SERVER['REMOTE_ADDR'];
|
||||
$attendance_stmt = $db->prepare("INSERT INTO attendance (user_id, login_time, ip_address) VALUES (:user_id, :login_time, :ip_address)");
|
||||
$attendance_stmt->bindParam(':user_id', $user['id']);
|
||||
$attendance_stmt->bindParam(':login_time', $login_time);
|
||||
$attendance_stmt->bindParam(':ip_address', $ip_address);
|
||||
$attendance_stmt->execute();
|
||||
$_SESSION['attendance_id'] = $db->lastInsertId();
|
||||
|
||||
switch ($role_name) {
|
||||
case 'admin':
|
||||
header("Location: admin_dashboard.php");
|
||||
break;
|
||||
case 'parent':
|
||||
header("Location: parent_dashboard.php");
|
||||
break;
|
||||
case 'student':
|
||||
header("Location: student_dashboard.php");
|
||||
break;
|
||||
case 'teacher':
|
||||
header("Location: teacher_dashboard.php");
|
||||
break;
|
||||
default:
|
||||
header("Location: index.php");
|
||||
break;
|
||||
}
|
||||
exit();
|
||||
} else {
|
||||
$error_message = 'Invalid username or password.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch header content
|
||||
ob_start();
|
||||
include 'index.php';
|
||||
$page_content = ob_get_clean();
|
||||
|
||||
// Extract only the <head> and <header>
|
||||
$head_and_header = '';
|
||||
if (preg_match('/<head>.*?<\/head>/s', $page_content, $head_match)) {
|
||||
$head_and_header .= $head_match[0];
|
||||
}
|
||||
if (preg_match('/<header>.*?<\/header>/s', $page_content, $header_match)) {
|
||||
$head_and_header .= $header_match[0];
|
||||
}
|
||||
|
||||
// Replace active nav link
|
||||
$head_and_header = str_replace('<a class="nav-link" href="index.php">Home</a>', '<a class="nav-link" href="index.php">Home</a>', $head_and_header);
|
||||
$head_and_header = preg_replace('/<a class="nav-link active" (.*?)>/', '<a class="nav-link" $1>', $head_and_header);
|
||||
|
||||
|
||||
echo str_replace('</head>', '<style>.login-container { max-width: 400px; margin: 5rem auto; }</style></head>', $head_and_header);
|
||||
|
||||
?>
|
||||
|
||||
<main class="container mt-5">
|
||||
<div class="login-container card">
|
||||
<div class="card-body">
|
||||
<h1 class="card-title text-center mb-4">Login</h1>
|
||||
<?php if ($error_message): ?>
|
||||
<div class="alert alert-danger"><?php echo $error_message; ?></div>
|
||||
<?php endif; ?>
|
||||
<form action="login.php" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary">Login</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
// Extract footer
|
||||
if (preg_match('/<footer.*?>.*?<\/footer>/s', $page_content, $footer_match)) {
|
||||
echo $footer_match[0];
|
||||
}
|
||||
?>
|
||||
18
logout.php
Normal file
18
logout.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (isset($_SESSION['attendance_id'])) {
|
||||
$db = db();
|
||||
$logout_time = date('Y-m-d H:i:s');
|
||||
$attendance_stmt = $db->prepare("UPDATE attendance SET logout_time = :logout_time WHERE id = :id");
|
||||
$attendance_stmt->bindParam(':logout_time', $logout_time);
|
||||
$attendance_stmt->bindParam(':id', $_SESSION['attendance_id']);
|
||||
$attendance_stmt->execute();
|
||||
}
|
||||
|
||||
session_unset();
|
||||
session_destroy();
|
||||
header("Location: login.php");
|
||||
exit();
|
||||
43
parent_dashboard.php
Normal file
43
parent_dashboard.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
// Authentication check
|
||||
if (!isset($_SESSION['user_id']) || empty($_SESSION['role_name']) || $_SESSION['role_name'] !== 'parent') {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Parent Dashboard</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<header class="p-3 mb-3 border-bottom sticky-top bg-light">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-dark text-decoration-none">
|
||||
<span class="fs-4">School Management</span>
|
||||
</a>
|
||||
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
|
||||
<li><a href="parent_dashboard.php" class="nav-link px-2 link-secondary">Dashboard</a></li>
|
||||
<li><a href="attendance.php" class="nav-link px-2 link-dark">Attendance</a></li>
|
||||
<li><a href="exams.php" class="nav-link px-2 link-dark">Exams</a></li>
|
||||
<li><a href="activities.php" class="nav-link px-2 link-dark">Activities</a></li>
|
||||
</ul>
|
||||
<div class="text-end">
|
||||
<a href="logout.php" class="btn btn-outline-primary">Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main class="container py-5">
|
||||
<h1>Welcome, Parent!</h1>
|
||||
<p>This is your dashboard.</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
183
roles.php
Normal file
183
roles.php
Normal file
@ -0,0 +1,183 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
// Authentication check
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['role_name'] !== 'admin') {
|
||||
//header('Location: login.php');
|
||||
//exit();
|
||||
}
|
||||
|
||||
require_once 'db/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Create roles table if it doesn't exist
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS roles (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
role_name VARCHAR(255) NOT NULL UNIQUE
|
||||
)");
|
||||
|
||||
// Function to log activity
|
||||
function log_activity($user_id, $action) {
|
||||
global $pdo;
|
||||
$stmt = $pdo->prepare("INSERT INTO activities (user_id, action) VALUES (:user_id, :action)");
|
||||
$stmt->execute(['user_id' => $user_id, 'action' => $action]);
|
||||
}
|
||||
|
||||
// Handle Create and Update
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['add_role'])) {
|
||||
$name = trim($_POST['role_name']);
|
||||
if (!empty($name)) {
|
||||
$stmt = $pdo->prepare("INSERT INTO roles (role_name) VALUES (:role_name)");
|
||||
$stmt->execute(['role_name' => $name]);
|
||||
$new_role_id = $pdo->lastInsertId();
|
||||
log_activity($_SESSION['user_id'], "Created role {$name} (ID: {$new_role_id})");
|
||||
}
|
||||
} elseif (isset($_POST['update_role'])) {
|
||||
$id = $_POST['role_id'];
|
||||
$name = trim($_POST['role_name']);
|
||||
if (!empty($name) && !empty($id)) {
|
||||
$stmt = $pdo->prepare("UPDATE roles SET role_name = :role_name WHERE id = :id");
|
||||
$stmt->execute(['role_name' => $name, 'id' => $id]);
|
||||
log_activity($_SESSION['user_id'], "Updated role {$name} (ID: {$id})");
|
||||
}
|
||||
}
|
||||
header("Location: roles.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle Delete
|
||||
if (isset($_GET['delete_id'])) {
|
||||
$id = $_GET['delete_id'];
|
||||
// Get role name for logging
|
||||
$stmt = $pdo->prepare("SELECT role_name FROM roles WHERE id = :id");
|
||||
$stmt->execute(['id' => $id]);
|
||||
$deleted_role = $stmt->fetch();
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM roles WHERE id = :id");
|
||||
$stmt->execute(['id' => $id]);
|
||||
|
||||
if ($deleted_role) {
|
||||
log_activity($_SESSION['user_id'], "Deleted role {$deleted_role['role_name']} (ID: {$id})");
|
||||
}
|
||||
header("Location: roles.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch all roles
|
||||
$roles = $pdo->query("SELECT * FROM roles ORDER BY id DESC")->fetchAll();
|
||||
|
||||
// Fetch role for editing
|
||||
$editing_role = null;
|
||||
if (isset($_GET['edit_id'])) {
|
||||
$id = $_GET['edit_id'];
|
||||
$stmt = $pdo->prepare("SELECT * FROM roles WHERE id = :id");
|
||||
$stmt->execute(['id' => $id]);
|
||||
$editing_role = $stmt->fetch();
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>مدیریت نقشها</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<script src="https://unpkg.com/feather-icons"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="p-3 mb-3 border-bottom sticky-top bg-light">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-dark text-decoration-none">
|
||||
<span class="fs-4">مدیریت مدرسه</span>
|
||||
</a>
|
||||
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
|
||||
<li><a href="index.php" class="nav-link px-2 link-dark">خانه</a></li>
|
||||
<li><a href="roles.php" class="nav-link px-2 link-secondary">مدیریت نقشها</a></li>
|
||||
<li><a href="users.php" class="nav-link px-2 link-dark">مدیریت کاربران</a></li>
|
||||
<li><a href="activities.php" class="nav-link px-2 link-dark">Activities</a></li>
|
||||
<li><a href="exams.php" class="nav-link px-2 link-dark">Exams</a></li>
|
||||
<li><a href="attendance.php" class="nav-link px-2 link-dark">Attendance</a></li>
|
||||
</ul>
|
||||
<div class="text-end">
|
||||
<?php if (isset($_SESSION['user_id'])): ?>
|
||||
<a href="logout.php" class="btn btn-outline-primary">خروج</a>
|
||||
<?php else: ?>
|
||||
<a href="login.php" class="btn btn-primary">ورود</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container py-5">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h2>فهرست نقشها</h2>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>نام نقش</th>
|
||||
<th>عملیات</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($roles as $role): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($role['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($role['role_name']); ?></td>
|
||||
<td>
|
||||
<a href="roles.php?edit_id=<?php echo $role['id']; ?>" class="btn btn-sm btn-outline-primary">ویرایش</a>
|
||||
<a href="roles.php?delete_id=<?php echo $role['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('آیا مطمئن هستید؟')">حذف</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h2><?php echo $editing_role ? 'ویرایش نقش' : 'افزودن نقش جدید'; ?></h2>
|
||||
<form method="POST" action="roles.php">
|
||||
<?php if ($editing_role): ?>
|
||||
<input type="hidden" name="role_id" value="<?php echo $editing_role['id']; ?>">
|
||||
<?php endif; ?>
|
||||
<div class="mb-3">
|
||||
<label for="role_name" class="form-label">نام نقش</label>
|
||||
<input type="text" class="form-control" id="role_name" name="role_name" value="<?php echo htmlspecialchars($editing_role['role_name'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<?php if ($editing_role): ?>
|
||||
<button type="submit" name="update_role" class="btn btn-primary w-100">بهروزرسانی</button>
|
||||
<a href="roles.php" class="btn btn-secondary w-100 mt-2">انصراف</a>
|
||||
<?php else: ?>
|
||||
<button type="submit" name="add_role" class="btn btn-success w-100">افزودن</button>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="footer mt-auto py-3 bg-light">
|
||||
<div class="container text-center">
|
||||
<span class="text-muted">© 2025 سیستم مدیریت مدرسه</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
feather.replace()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
43
student_dashboard.php
Normal file
43
student_dashboard.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
// Authentication check
|
||||
if (!isset($_SESSION['user_id']) || empty($_SESSION['role_name']) || $_SESSION['role_name'] !== 'student') {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Student Dashboard</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<header class="p-3 mb-3 border-bottom sticky-top bg-light">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-dark text-decoration-none">
|
||||
<span class="fs-4">School Management</span>
|
||||
</a>
|
||||
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
|
||||
<li><a href="student_dashboard.php" class="nav-link px-2 link-secondary">Dashboard</a></li>
|
||||
<li><a href="attendance.php" class="nav-link px-2 link-dark">Attendance</a></li>
|
||||
<li><a href="exams.php" class="nav-link px-2 link-dark">Exams</a></li>
|
||||
<li><a href="activities.php" class="nav-link px-2 link-dark">Activities</a></li>
|
||||
</ul>
|
||||
<div class="text-end">
|
||||
<a href="logout.php" class="btn btn-outline-primary">Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main class="container py-5">
|
||||
<h1>Welcome, Student!</h1>
|
||||
<p>This is your dashboard.</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
133
take_exam.php
Normal file
133
take_exam.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'student') {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$pdo = db();
|
||||
|
||||
if (!isset($_GET['student_exam_id'])) {
|
||||
header('Location: exams.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$student_exam_id = $_GET['student_exam_id'];
|
||||
|
||||
// Verify student is assigned to this exam
|
||||
$stmt = $pdo->prepare('SELECT * FROM student_exams WHERE id = ? AND student_id = ?');
|
||||
$stmt->execute([$student_exam_id, $user_id]);
|
||||
$student_exam = $stmt->fetch();
|
||||
|
||||
if (!$student_exam) {
|
||||
echo "You are not assigned to this exam.";
|
||||
exit();
|
||||
}
|
||||
|
||||
// Prevent re-taking a completed exam
|
||||
if ($student_exam['status'] === 'completed') {
|
||||
echo "You have already completed this exam.";
|
||||
// Maybe redirect to a results page in the future
|
||||
echo '<br><a href="exams.php">Back to Exams</a>';
|
||||
exit();
|
||||
}
|
||||
|
||||
// Fetch exam details
|
||||
$stmt = $pdo->prepare('SELECT * FROM exams WHERE id = ?');
|
||||
$stmt->execute([$student_exam['exam_id']]);
|
||||
$exam = $stmt->fetch();
|
||||
|
||||
// Fetch exam questions
|
||||
$stmt = $pdo->prepare('SELECT * FROM exam_questions WHERE exam_id = ? ORDER BY id ASC');
|
||||
$stmt->execute([$exam['id']]);
|
||||
$questions = $stmt->fetchAll();
|
||||
|
||||
// Handle exam submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['answers'])) {
|
||||
$answers = $_POST['answers'];
|
||||
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
foreach ($answers as $question_id => $answer_text) {
|
||||
// Use INSERT ... ON DUPLICATE KEY UPDATE to prevent duplicate answer submissions
|
||||
$sql = 'INSERT INTO student_answers (student_exam_id, question_id, answer_text) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE answer_text = VALUES(answer_text)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$student_exam_id, $question_id, trim($answer_text)]);
|
||||
}
|
||||
|
||||
// Mark exam as completed
|
||||
$stmt = $pdo->prepare('UPDATE student_exams SET status = \'completed\' WHERE id = ?');
|
||||
$stmt->execute([$student_exam_id]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
header('Location: exams.php');
|
||||
exit();
|
||||
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
// Log error properly in a real application
|
||||
die("An error occurred while submitting your exam. Please try again. Error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// If student is starting the exam, mark it as 'in-progress'
|
||||
if ($student_exam['status'] === 'assigned') {
|
||||
$stmt = $pdo->prepare('UPDATE student_exams SET status = \'in-progress\' WHERE id = ?');
|
||||
$stmt->execute([$student_exam_id]);
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Take Exam: <?php echo htmlspecialchars($exam['name']); ?></title>
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1><?php echo htmlspecialchars($exam['name']); ?></h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="exams.php">Back to Exams</a></li>
|
||||
<li><a href="logout.php">Logout</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<form action="take_exam.php?student_exam_id=<?php echo $student_exam_id; ?>" method="POST">
|
||||
<?php foreach ($questions as $index => $q): ?>
|
||||
<div class="question-block">
|
||||
<p><strong>Question <?php echo $index + 1; ?>:</strong> <?php echo nl2br(htmlspecialchars($q['question_text'])); ?></p>
|
||||
|
||||
<?php if ($q['question_type'] === 'multiple_choice'): ?>
|
||||
<?php $options = json_decode($q['options']); ?>
|
||||
<?php if($options):
|
||||
foreach ($options as $option):
|
||||
?>
|
||||
<div>
|
||||
<input type="radio" id="q_<?php echo $q['id'] . '_' . htmlspecialchars($option); ?>" name="answers[<?php echo $q['id']; ?>]" value="<?php echo htmlspecialchars($option); ?>" required>
|
||||
<label for="q_<?php echo $q['id'] . '_' . htmlspecialchars($option); ?>"><?php echo htmlspecialchars($option); ?></label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
<?php else: // free_text ?>
|
||||
<textarea name="answers[<?php echo $q['id']; ?>]" rows="5" required></textarea>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (empty($questions)): ?>
|
||||
<p>This exam has no questions.</p>
|
||||
<?php else: ?>
|
||||
<button type="submit" onclick="return confirm('Are you sure you want to submit your answers?');">Submit Exam</button>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
43
teacher_dashboard.php
Normal file
43
teacher_dashboard.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
// Authentication check
|
||||
if (!isset($_SESSION['user_id']) || empty($_SESSION['role_name']) || $_SESSION['role_name'] !== 'teacher') {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Teacher Dashboard</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<header class="p-3 mb-3 border-bottom sticky-top bg-light">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-dark text-decoration-none">
|
||||
<span class="fs-4">School Management</span>
|
||||
</a>
|
||||
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
|
||||
<li><a href="teacher_dashboard.php" class="nav-link px-2 link-secondary">Dashboard</a></li>
|
||||
<li><a href="attendance.php" class="nav-link px-2 link-dark">Attendance</a></li>
|
||||
<li><a href="exams.php" class="nav-link px-2 link-dark">Exams</a></li>
|
||||
<li><a href="activities.php" class="nav-link px-2 link-dark">Activities</a></li>
|
||||
</ul>
|
||||
<div class="text-end">
|
||||
<a href="logout.php" class="btn btn-outline-primary">Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main class="container py-5">
|
||||
<h1>Welcome, Teacher!</h1>
|
||||
<p>This is your dashboard.</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
318
users.php
Normal file
318
users.php
Normal file
@ -0,0 +1,318 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
// Authentication check
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['role_name'] !== 'admin') {
|
||||
//header('Location: login.php');
|
||||
//exit();
|
||||
}
|
||||
|
||||
require_once 'db/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Create users table if it doesn't exist
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(255) NOT NULL UNIQUE,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role_id INT,
|
||||
first_name VARCHAR(255),
|
||||
last_name VARCHAR(255),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE SET NULL
|
||||
)");
|
||||
|
||||
// Fetch all roles for the dropdown
|
||||
$roles = $pdo->query("SELECT * FROM roles ORDER BY role_name")->fetchAll();
|
||||
|
||||
// Function to log activity
|
||||
function log_activity($user_id, $action) {
|
||||
global $pdo;
|
||||
$stmt = $pdo->prepare("INSERT INTO activities (user_id, action) VALUES (:user_id, :action)");
|
||||
$stmt->execute(['user_id' => $user_id, 'action' => $action]);
|
||||
}
|
||||
|
||||
// Handle Create and Update
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['add_user'])) {
|
||||
$username = trim($_POST['username']);
|
||||
$email = trim($_POST['email']);
|
||||
$password = $_POST['password'];
|
||||
$role_id = $_POST['role_id'];
|
||||
$first_name = trim($_POST['first_name']);
|
||||
$last_name = trim($_POST['last_name']);
|
||||
|
||||
if (!empty($username) && !empty($email) && !empty($password) && !empty($role_id)) {
|
||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("INSERT INTO users (username, email, password, role_id, first_name, last_name) VALUES (:username, :email, :password, :role_id, :first_name, :last_name)");
|
||||
$stmt->execute([
|
||||
'username' => $username,
|
||||
'email' => $email,
|
||||
'password' => $hashed_password,
|
||||
'role_id' => $role_id,
|
||||
'first_name' => $first_name,
|
||||
'last_name' => $last_name
|
||||
]);
|
||||
$new_user_id = $pdo->lastInsertId();
|
||||
log_activity($_SESSION['user_id'], "Created user {$username} (ID: {$new_user_id})");
|
||||
}
|
||||
} elseif (isset($_POST['update_user'])) {
|
||||
$id = $_POST['user_id'];
|
||||
$username = trim($_POST['username']);
|
||||
$email = trim($_POST['email']);
|
||||
$password = $_POST['password'];
|
||||
$role_id = $_POST['role_id'];
|
||||
$first_name = trim($_POST['first_name']);
|
||||
$last_name = trim($_POST['last_name']);
|
||||
|
||||
if (!empty($id) && !empty($username) && !empty($email) && !empty($role_id)) {
|
||||
if (!empty($password)) {
|
||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("UPDATE users SET username = :username, email = :email, password = :password, role_id = :role_id, first_name = :first_name, last_name = :last_name WHERE id = :id");
|
||||
$stmt->execute([
|
||||
'username' => $username,
|
||||
'email' => $email,
|
||||
'password' => $hashed_password,
|
||||
'role_id' => $role_id,
|
||||
'first_name' => $first_name,
|
||||
'last_name' => $last_name,
|
||||
'id' => $id
|
||||
]);
|
||||
} else {
|
||||
$stmt = $pdo->prepare("UPDATE users SET username = :username, email = :email, role_id = :role_id, first_name = :first_name, last_name = :last_name WHERE id = :id");
|
||||
$stmt->execute([
|
||||
'username' => $username,
|
||||
'email' => $email,
|
||||
'role_id' => $role_id,
|
||||
'first_name' => $first_name,
|
||||
'last_name' => $last_name,
|
||||
'id' => $id
|
||||
]);
|
||||
}
|
||||
log_activity($_SESSION['user_id'], "Updated user {$username} (ID: {$id})");
|
||||
} elseif (isset($_POST['link_parent_child'])) {
|
||||
$parent_id = $_POST['parent_id'];
|
||||
$child_id = $_POST['child_id'];
|
||||
|
||||
if (!empty($parent_id) && !empty($child_id)) {
|
||||
$stmt = $pdo->prepare("INSERT INTO parent_child (parent_id, child_id) VALUES (:parent_id, :child_id)");
|
||||
$stmt->execute(['parent_id' => $parent_id, 'child_id' => $child_id]);
|
||||
log_activity($_SESSION['user_id'], "Linked parent (ID: {$parent_id}) to child (ID: {$child_id})");
|
||||
}
|
||||
header("Location: users.php?link_success=1");
|
||||
exit;
|
||||
}
|
||||
header("Location: users.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle Delete
|
||||
if (isset($_GET['delete_id'])) {
|
||||
$id = $_GET['delete_id'];
|
||||
// Get username for logging
|
||||
$stmt = $pdo->prepare("SELECT username FROM users WHERE id = :id");
|
||||
$stmt->execute(['id' => $id]);
|
||||
$deleted_user = $stmt->fetch();
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
|
||||
$stmt->execute(['id' => $id]);
|
||||
|
||||
if ($deleted_user) {
|
||||
log_activity($_SESSION['user_id'], "Deleted user {$deleted_user['username']} (ID: {$id})");
|
||||
}
|
||||
header("Location: users.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch all users with their role names
|
||||
$users = $pdo->query("
|
||||
SELECT users.*, roles.role_name AS role_name
|
||||
FROM users
|
||||
LEFT JOIN roles ON users.role_id = roles.id
|
||||
ORDER BY users.id DESC
|
||||
")->fetchAll();
|
||||
|
||||
// Fetch all parents and students
|
||||
$parents = $pdo->query("SELECT u.id, u.first_name, u.last_name FROM users u JOIN roles r ON u.role_id = r.id WHERE r.role_name = 'parent'")->fetchAll();
|
||||
$students = $pdo->query("SELECT u.id, u.first_name, u.last_name FROM users u JOIN roles r ON u.role_id = r.id WHERE r.role_name = 'student'")->fetchAll();
|
||||
|
||||
// Fetch user for editing
|
||||
$editing_user = null;
|
||||
if (isset($_GET['edit_id'])) {
|
||||
$id = $_GET['edit_id'];
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
|
||||
$stmt->execute(['id' => $id]);
|
||||
$editing_user = $stmt->fetch();
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>مدیریت کاربران</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<script src="https://unpkg.com/feather-icons"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="p-3 mb-3 border-bottom sticky-top bg-light">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-dark text-decoration-none">
|
||||
<span class="fs-4">مدیریت مدرسه</span>
|
||||
</a>
|
||||
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
|
||||
<li><a href="index.php" class="nav-link px-2 link-dark">خانه</a></li>
|
||||
<li><a href="roles.php" class="nav-link px-2 link-dark">مدیریت نقشها</a></li>
|
||||
<li><a href="users.php" class="nav-link px-2 link-secondary">مدیریت کاربران</a></li>
|
||||
<li><a href="activities.php" class="nav-link px-2 link-dark">Activities</a></li>
|
||||
<li><a href="exams.php" class="nav-link px-2 link-dark">Exams</a></li>
|
||||
<li><a href="attendance.php" class="nav-link px-2 link-dark">Attendance</a></li>
|
||||
</ul>
|
||||
<div class="text-end">
|
||||
<?php if (isset($_SESSION['user_id'])): ?>
|
||||
<a href="logout.php" class="btn btn-outline-primary">خروج</a>
|
||||
<?php else: ?>
|
||||
<a href="login.php" class="btn btn-primary">ورود</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container py-5">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h2>فهرست کاربران</h2>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>نام کاربری</th>
|
||||
<th>ایمیل</th>
|
||||
<th>نقش</th>
|
||||
<th>عملیات</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($users as $user): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($user['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($user['username']); ?></td>
|
||||
<td><?php echo htmlspecialchars($user['email']); ?></td>
|
||||
<td><?php echo htmlspecialchars($user['role_name'] ?? 'بدون نقش'); ?></td>
|
||||
<td>
|
||||
<a href="users.php?edit_id=<?php echo $user['id']; ?>" class="btn btn-sm btn-outline-primary">ویرایش</a>
|
||||
<a href="users.php?delete_id=<?php echo $user['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('آیا مطمئن هستید؟')">حذف</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h2><?php echo $editing_user ? 'ویرایش کاربر' : 'افزودن کاربر جدید'; ?></h2>
|
||||
<form method="POST" action="users.php">
|
||||
<?php if ($editing_user): ?>
|
||||
<input type="hidden" name="user_id" value="<?php echo $editing_user['id']; ?>">
|
||||
<?php endif; ?>
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">نام کاربری</label>
|
||||
<input type="text" class="form-control" id="username" name="username" value="<?php echo htmlspecialchars($editing_user['username'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">ایمیل</label>
|
||||
<input type="email" class="form-control" id="email" name="email" value="<?php echo htmlspecialchars($editing_user['email'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="first_name" class="form-label">نام</label>
|
||||
<input type="text" class="form-control" id="first_name" name="first_name" value="<?php echo htmlspecialchars($editing_user['first_name'] ?? ''); ?>">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="last_name" class="form-label">نام خانوادگی</label>
|
||||
<input type="text" class="form-control" id="last_name" name="last_name" value="<?php echo htmlspecialchars($editing_user['last_name'] ?? ''); ?>">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">رمز عبور <?php echo $editing_user ? '(خالی بگذارید تا بدون تغییر بماند)' : ''; ?></label>
|
||||
<input type="password" class="form-control" id="password" name="password" <?php echo !$editing_user ? 'required' : ''; ?>>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="role_id" class="form-label">نقش</label>
|
||||
<select class="form-select" id="role_id" name="role_id" required>
|
||||
<option value="">یک نقش انتخاب کنید</option>
|
||||
<?php foreach ($roles as $role): ?>
|
||||
<option value="<?php echo $role['id']; ?>" <?php echo (isset($editing_user) && $editing_user['role_id'] == $role['id']) ? 'selected' : ''; ?>>
|
||||
<?php echo htmlspecialchars($role['role_name']); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php if ($editing_user): ?>
|
||||
<button type="submit" name="update_user" class="btn btn-primary w-100">بهروزرسانی</button>
|
||||
<a href="users.php" class="btn btn-secondary w-100 mt-2">انصراف</a>
|
||||
<?php else: ?>
|
||||
<button type="submit" name="add_user" class="btn btn-success w-100">افزودن</button>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-5">
|
||||
<div class="col-md-12">
|
||||
<h2>Link Parent to Child</h2>
|
||||
<?php if (isset($_GET['link_success'])): ?>
|
||||
<div class="alert alert-success">Parent and child linked successfully.</div>
|
||||
<?php endif; ?>
|
||||
<form method="POST" action="users.php">
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<label for="parent_id" class="form-label">Parent</label>
|
||||
<select class="form-select" id="parent_id" name="parent_id" required>
|
||||
<option value="">Select a parent</option>
|
||||
<?php foreach ($parents as $parent): ?>
|
||||
<option value="<?php echo $parent['id']; ?>"><?php echo htmlspecialchars($parent['first_name'] . ' ' . $parent['last_name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label for="child_id" class="form-label">Child</label>
|
||||
<select class="form-select" id="child_id" name="child_id" required>
|
||||
<option value="">Select a child</option>
|
||||
<?php foreach ($students as $student): ?>
|
||||
<option value="<?php echo $student['id']; ?>"><?php echo htmlspecialchars($student['first_name'] . ' ' . $student['last_name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<button type="submit" name="link_parent_child" class="btn btn-primary w-100">Link</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="footer mt-auto py-3 bg-light">
|
||||
<div class="container text-center">
|
||||
<span class="text-muted">© 2025 سیستم مدیریت مدرسه</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
feather.replace()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user