v3
This commit is contained in:
parent
ea73dc7483
commit
20f916f31d
60
admin_panel.php
Normal file
60
admin_panel.php
Normal 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'; ?>
|
||||
BIN
assets/pasted-20251204-152901-9d863924.jpg
Normal file
BIN
assets/pasted-20251204-152901-9d863924.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
BIN
assets/vm-shot-2025-12-04T15-27-54-201Z.jpg
Normal file
BIN
assets/vm-shot-2025-12-04T15-27-54-201Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
@ -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>
|
||||
|
||||
13
register.php
13
register.php
@ -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
52
retake_test.php
Normal 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
|
||||
?>
|
||||
@ -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
|
||||
|
||||
129
take_test.php
129
take_test.php
@ -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'; ?>
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user