This commit is contained in:
Flatlogic Bot 2025-12-08 05:38:25 +00:00
parent ea73dc7483
commit 20f916f31d
9 changed files with 248 additions and 30 deletions

60
admin_panel.php Normal file
View File

@ -0,0 +1,60 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'psychologist') {
header('Location: login.php');
exit();
}
$pdo = db();
$stmt = $pdo->query("
SELECT u.username, t.title, ut.score, ut.completed_at
FROM user_tests ut
JOIN users u ON ut.user_id = u.id
JOIN tests t ON ut.test_id = t.id
ORDER BY ut.completed_at DESC
");
$results = $stmt->fetchAll();
require_once 'includes/header.php';
?>
<div class="container">
<h1 class="mt-5">Панель психолога</h1>
<p class="lead">Добро пожаловать, <?php echo htmlspecialchars($_SESSION['username']); ?>!</p>
<h2 class="mt-4">Результаты тестов</h2>
<?php if (empty($results)): ?>
<div class="alert alert-info mt-3" role="alert">
Пока нет ни одного пройденного теста.
</div>
<?php else: ?>
<div class="table-responsive mt-3">
<table class="table table-bordered table-hover">
<thead class="table-light">
<tr>
<th scope="col">Пользователь</th>
<th scope="col">Тест</th>
<th scope="col">Баллы</th>
<th scope="col">Дата</th>
</tr>
</thead>
<tbody>
<?php foreach ($results as $result): ?>
<tr>
<td><?php echo htmlspecialchars($result['username']); ?></td>
<td><?php echo htmlspecialchars($result['title']); ?></td>
<td><?php echo htmlspecialchars($result['score']); ?></td>
<td><?php echo date('d.m.Y H:i', strtotime($result['completed_at'])); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
<?php require_once 'includes/footer.php'; ?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -28,7 +28,13 @@ if (session_status() === PHP_SESSION_NONE) {
<li class="nav-item">
<span class="nav-link">Welcome, <?php echo htmlspecialchars($_SESSION['username']); ?>!</span>
</li>
<li class="nav-item">
<a class="nav-link" href="index.php">Tests</a>
</li>
<?php if ($_SESSION['role'] === 'psychologist'): ?>
<li class="nav-item">
<a class="nav-link" href="admin_panel.php">Admin Panel</a>
</li>
<li class="nav-item">
<a class="nav-link" href="create_test.php">Create Test</a>
</li>

View File

@ -8,9 +8,9 @@ $success = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = trim($_POST['username']);
$password = $_POST['password'];
$role = $_POST['role'];
$role = $_POST['role'] ?? 'user';
if (empty($username) || empty($password) || empty($role)) {
if (empty($username) || empty($password)) {
$error = 'Please fill in all fields.';
} elseif (strlen($password) < 6) {
$error = 'Password must be at least 6 characters long.';
@ -79,13 +79,14 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="mb-4">
<label for="role" class="form-label">I am a...</label>
<div class="mb-3">
<label for="role" class="form-label">Register as</label>
<select class="form-select" id="role" name="role">
<option value="user" selected>User (taking tests)</option>
<option value="psychologist">Psychologist (creating tests)</option>
<option value="user" selected>User</option>
<option value="psychologist">Psychologist</option>
</select>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">Register</button>
</div>

52
retake_test.php Normal file
View File

@ -0,0 +1,52 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
// Redirect if not logged in
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit();
}
// Check for test ID
if (!isset($_GET['test_id']) || !is_numeric($_GET['test_id'])) {
// Redirect to home or show an error
header('Location: index.php');
exit();
}
$test_id = intval($_GET['test_id']);
$user_id = $_SESSION['user_id'];
try {
$db = db();
// Start a transaction
$db->beginTransaction();
// Delete from user_answers
$stmt_answers = $db->prepare("DELETE FROM user_answers WHERE user_id = :user_id AND question_id IN (SELECT id FROM questions WHERE test_id = :test_id)");
$stmt_answers->execute(['user_id' => $user_id, 'test_id' => $test_id]);
// Delete from user_tests
$stmt_tests = $db->prepare("DELETE FROM user_tests WHERE user_id = :user_id AND test_id = :test_id");
$stmt_tests->execute(['user_id' => $user_id, 'test_id' => $test_id]);
// Commit the transaction
$db->commit();
// Redirect to the test page
header('Location: take_test.php?test_id=' . $test_id);
exit();
} catch (PDOException $e) {
// Rollback the transaction if something failed
if ($db->inTransaction()) {
$db->rollBack();
}
// You might want to log this error instead of showing it to the user
die("Database error while trying to reset the test. Please try again.");
}
// No need for footer as we are redirecting
?>

View File

@ -32,13 +32,24 @@ try {
// Begin transaction
$db->beginTransaction();
// Prepare statement for inserting or updating user answers
$answerStmt = $db->prepare(
"INSERT INTO user_answers (user_id, question_id, option_id) VALUES (:user_id, :question_id, :option_id)
ON DUPLICATE KEY UPDATE option_id = VALUES(option_id)"
);
// Calculate total score
// Calculate total score and insert individual answers
foreach ($answers as $question_id => $option_id) {
if (isset($scores[$option_id])) {
$total_score += $scores[$option_id];
}
// Insert the answer
$answerStmt->execute([
'user_id' => $user_id,
'question_id' => $question_id,
'option_id' => $option_id
]);
}
// Save the final score in the user_tests table

View File

@ -20,17 +20,16 @@ $user_id = $_SESSION['user_id'];
try {
$db = db();
// Check if user has already taken this test
$checkStmt = $db->prepare("SELECT COUNT(*) FROM user_tests WHERE user_id = :user_id AND test_id = :test_id");
$checkStmt->execute(['user_id' => $user_id, 'test_id' => $test_id]);
if ($checkStmt->fetchColumn() > 0) {
echo "<div class='container mt-5'><div class='alert alert-info'>You have already completed this test. <a href='test_results.php?test_id=$test_id'>View your results</a>.</div></div>";
require_once 'includes/footer.php';
exit();
echo "<div class='container mt-5'><div class='alert alert-info'>You have already completed this test. <a href='test_results.php?test_id=$test_id'>View your results</a>.</div></div>";
require_once 'includes/footer.php';
exit();
}
// Fetch test details
$stmt = $db->prepare("SELECT title, description FROM tests WHERE id = :id");
$stmt->execute(['id' => $test_id]);
@ -52,12 +51,33 @@ try {
");
$questionsStmt->execute(['test_id' => $test_id]);
$questionsData = $questionsStmt->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);
$question_keys = array_keys($questionsData);
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
?>
<style>
.question-container {
display: none;
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
.question-container.active {
display: block;
opacity: 1;
}
.progress-bar-container {
width: 100%;
background-color: #e9ecef;
border-radius: .25rem;
}
.progress-bar-fill {
height: 10px;
background-color: #28a745;
border-radius: .25rem;
transition: width 0.3s ease-in-out;
}
</style>
<div class="container mt-5">
<div class="card">
@ -67,31 +87,98 @@ try {
<div class="card-body">
<p class="lead"><?php echo nl2br(htmlspecialchars($test['description'])); ?></p>
<hr>
<?php if (empty($questionsData)): ?>
<div class="alert alert-warning">This test has no questions yet.</div>
<?php else: ?>
<form action="submit_test.php" method="post">
<div class="progress-bar-container mb-4">
<div class="progress-bar-fill" id="progress-bar"></div>
</div>
<p id="progress-text" class="text-center"></p>
<form id="test-form" action="submit_test.php" method="post">
<input type="hidden" name="test_id" value="<?php echo $test_id; ?>">
<?php foreach ($questionsData as $question_id => $options): ?>
<div class="mb-4">
<h5><?php echo htmlspecialchars($options[0]['question_text']); ?></h5>
<?php foreach ($options as $option): ?>
<div class="form-check">
<input class="form-check-input" type="radio" name="answers[<?php echo $question_id; ?>]" id="option_<?php echo $option['option_id']; ?>" value="<?php echo $option['option_id']; ?>" required>
<label class="form-check-label" for="option_<?php echo $option['option_id']; ?>">
<?php echo htmlspecialchars($option['option_text']); ?>
</label>
</div>
<?php endforeach; ?>
<?php foreach ($question_keys as $index => $question_id):
$options = $questionsData[$question_id];
$is_first = ($index === 0);
$is_last = ($index === count($question_keys) - 1);
?>
<div class="question-container <?php if ($is_first) echo 'active'; ?>" data-question-index="<?php echo $index; ?>">
<div class="mb-4">
<h5><?php echo htmlspecialchars($options[0]['question_text']); ?></h5>
<?php foreach ($options as $option): ?>
<div class="form-check">
<input class="form-check-input" type="radio" name="answers[<?php echo $question_id; ?>]" id="option_<?php echo $option['option_id']; ?>" value="<?php echo $option['option_id']; ?>" required>
<label class="form-check-label" for="option_<?php echo $option['option_id']; ?>">
<?php echo htmlspecialchars($option['option_text']); ?>
</label>
</div>
<?php endforeach; ?>
</div>
<div class="d-flex justify-content-between">
<?php if (!$is_first): ?>
<button type="button" class="btn btn-secondary btn-prev">Previous</button>
<?php endif; ?>
<?php if (!$is_last): ?>
<button type="button" class="btn btn-primary btn-next ml-auto">Next</button>
<?php endif; ?>
<?php if ($is_last): ?>
<button type="submit" class="btn btn-success ml-auto">Submit Answers</button>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<button type="submit" class="btn btn-success">Submit Answers</button>
</form>
<?php endif; ?>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const questions = document.querySelectorAll('.question-container');
const progressBar = document.getElementById('progress-bar');
const progressText = document.getElementById('progress-text');
let currentQuestionIndex = 0;
const totalQuestions = questions.length;
function updateProgress() {
const progressPercentage = ((currentQuestionIndex + 1) / totalQuestions) * 100;
progressBar.style.width = progressPercentage + '%';
progressText.textContent = `Question ${currentQuestionIndex + 1} of ${totalQuestions}`;
}
function showQuestion(index) {
questions.forEach((question, i) => {
if (i === index) {
question.classList.add('active');
} else {
question.classList.remove('active');
}
});
currentQuestionIndex = index;
updateProgress();
}
document.getElementById('test-form').addEventListener('click', function(e) {
if (e.target.classList.contains('btn-next')) {
const currentQuestion = questions[currentQuestionIndex];
const radio = currentQuestion.querySelector('input[type="radio"]:checked');
if(radio){
showQuestion(currentQuestionIndex + 1);
} else {
alert('Please select an answer.');
}
}
if (e.target.classList.contains('btn-prev')) {
showQuestion(currentQuestionIndex - 1);
}
});
// Initial setup
showQuestion(0);
});
</script>
<?php require_once 'includes/footer.php'; ?>

View File

@ -58,7 +58,8 @@ try {
<?php endif; ?>
</div>
<div class="card-footer text-muted">
<a href="index.php" class="btn btn-primary">Back to Test List</a>
<a href="index.php" class="btn btn-secondary">Back to Test List</a>
<a href="retake_test.php?test_id=<?php echo $test_id; ?>" class="btn btn-primary">Retake Test</a>
</div>
</div>
</div>