<?php
// Start session
session_start();
// Include database configuration
require_once '../config/database.php';
// Include header and sidebar
include_once 'includes/header.php';
include_once 'includes/sidebar.php';
// Check if user is logged in and has admin or director role
if (!isset($_SESSION['user_id']) || ($_SESSION['role'] !== 'admin' && $_SESSION['role'] !== 'director')) {
header('Location: login.php');
exit;
}
// Check if exam_id is provided
if (!isset($_GET['exam_id']) || empty($_GET['exam_id'])) {
$_SESSION['error'] = "Invalid exam ID";
header('Location: manage_exams.php');
exit;
}
$exam_id = $_GET['exam_id'];
// Get exam details
$exam_query = "SELECT es.*, c.title as course_title FROM exam_schedules es
LEFT JOIN courses c ON es.course_id = c.id
WHERE es.id = ?";
$stmt = $conn->prepare($exam_query);
$stmt->bind_param("i", $exam_id);
$stmt->execute();
$exam_result = $stmt->get_result();
if ($exam_result->num_rows === 0) {
$_SESSION['error'] = "Exam not found";
header('Location: manage_exams.php');
exit;
}
$exam = $exam_result->fetch_assoc();
// Handle form submission for adding questions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['add_question'])) {
// Get form data
$question_text = trim($_POST['question_text']);
$question_type = $_POST['question_type'];
$marks = $_POST['marks'];
$options = isset($_POST['options']) ? $_POST['options'] : [];
$correct_answers = isset($_POST['correct_answers']) ? $_POST['correct_answers'] : [];
// Validate input
$errors = [];
if (empty($question_text)) {
$errors[] = "Question text is required";
}
if (empty($marks) || !is_numeric($marks) || $marks <= 0) {
$errors[] = "Marks must be a positive number";
}
if ($question_type === 'multiple_choice' || $question_type === 'single_choice') {
// Check if at least 2 options are provided
if (count(array_filter($options)) < 2) {
$errors[] = "At least 2 options are required";
}
// Check if at least one correct answer is selected
if (empty($correct_answers)) {
$errors[] = "Please select at least one correct answer";
}
// For single choice, only one answer should be selected
if ($question_type === 'single_choice' && count($correct_answers) > 1) {
$errors[] = "Only one correct answer allowed for single choice questions";
}
}
// If no errors, insert the question
if (empty($errors)) {
// Begin transaction
$conn->begin_transaction();
try {
// Insert question
$question_query = "INSERT INTO exam_questions (exam_id, question_text, question_type, marks)
VALUES (?, ?, ?, ?)";
$question_stmt = $conn->prepare($question_query);
$question_stmt->bind_param("issi", $exam_id, $question_text, $question_type, $marks);
$question_stmt->execute();
$question_id = $conn->insert_id;
// Insert options if applicable
if ($question_type === 'multiple_choice' || $question_type === 'single_choice') {
foreach ($options as $key => $option_text) {
if (!empty($option_text)) {
$is_correct = in_array($key, $correct_answers) ? 1 : 0;
$option_query = "INSERT INTO question_options (question_id, option_text, is_correct)
VALUES (?, ?, ?)";
$option_stmt = $conn->prepare($option_query);
$option_stmt->bind_param("isi", $question_id, $option_text, $is_correct);
$option_stmt->execute();
}
}
}
// Commit transaction
$conn->commit();
$_SESSION['success'] = "Question added successfully";
header("Location: add_exam_questions.php?exam_id=" . $exam_id);
exit;
} catch (Exception $e) {
// Rollback transaction on error
$conn->rollback();
$_SESSION['error'] = "Error adding question: " . $e->getMessage();
}
}
}
}
// Get questions for this exam
$questions_query = "SELECT * FROM exam_questions WHERE exam_id = ? ORDER BY id";
$questions_stmt = $conn->prepare($questions_query);
$questions_stmt->bind_param("i", $exam_id);
$questions_stmt->execute();
$questions_result = $questions_stmt->get_result();
?>
<div class="content-wrapper">
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0">Add Questions to Exam</h1>
<p class="text-muted">
<i class="fas fa-book"></i> <?php echo htmlspecialchars($exam['title']); ?> -
<i class="fas fa-graduation-cap"></i> <?php echo htmlspecialchars($exam['course_title']); ?>
</p>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="index.php">Home</a></li>
<li class="breadcrumb-item"><a href="manage_exams.php">Manage Exams</a></li>
<li class="breadcrumb-item active">Add Questions</li>
</ol>
</div>
</div>
</div>
</div>
<section class="content">
<div class="container-fluid">
<?php if (isset($_SESSION['success'])): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<h5><i class="icon fas fa-check"></i> Success!</h5>
<?php
echo $_SESSION['success'];
unset($_SESSION['success']);
?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<?php endif; ?>
<?php if (isset($_SESSION['error'])): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<h5><i class="icon fas fa-ban"></i> Error!</h5>
<?php
echo $_SESSION['error'];
unset($_SESSION['error']);
?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<?php endif; ?>
<?php if (isset($errors) && !empty($errors)): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<h5><i class="icon fas fa-ban"></i> Error!</h5>
<ul>
<?php foreach ($errors as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<?php endif; ?>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h3 class="card-title">Current Questions (<?php echo $questions_result->num_rows; ?>)</h3>
<div class="card-tools">
<a href="manage_exams.php" class="btn btn-sm btn-secondary">
<i class="fas fa-arrow-left"></i> Back to Exams
</a>
<button type="button" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#addQuestionModal">
<i class="fas fa-plus"></i> Add New Question
</button>
</div>
</div>
<div class="card-body">
<?php if ($questions_result->num_rows === 0): ?>
<div class="alert alert-info">
<i class="fas fa-info-circle"></i> No questions have been added to this exam yet. Click "Add New Question" to get started.
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th style="width: 50px;">#</th>
<th>Question</th>
<th style="width: 120px;">Type</th>
<th style="width: 100px;">Marks</th>
<th style="width: 150px;">Actions</th>
</tr>
</thead>
<tbody>
<?php
$count = 1;
while ($question = $questions_result->fetch_assoc()):
?>
<tr>
<td><?php echo $count++; ?></td>
<td><?php echo htmlspecialchars(substr($question['question_text'], 0, 100)) . (strlen($question['question_text']) > 100 ? '...' : ''); ?></td>
<td>
<?php if ($question['question_type'] === 'single_choice'): ?>
<span class="badge badge-info">Single Choice</span>
<?php elseif ($question['question_type'] === 'multiple_choice'): ?>
<span class="badge badge-primary">Multiple Choice</span>
<?php elseif ($question['question_type'] === 'text'): ?>
<span class="badge badge-secondary">Text</span>
<?php endif; ?>
</td>
<td><?php echo $question['marks']; ?></td>
<td>
<button type="button" class="btn btn-sm btn-info view-question" data-id="<?php echo $question['id']; ?>">
<i class="fas fa-eye"></i>
</button>
<button type="button" class="btn btn-sm btn-danger delete-question" data-id="<?php echo $question['id']; ?>">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<!-- Add Question Modal -->
<div class="modal fade" id="addQuestionModal" tabindex="-1" role="dialog" aria-labelledby="addQuestionModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addQuestionModalLabel">Add New Question</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form action="" method="POST" id="addQuestionForm">
<div class="form-group">
<label for="question_text">Question <span class="text-danger">*</span></label>
<textarea class="form-control" id="question_text" name="question_text" rows="3" required><?php echo isset($_POST['question_text']) ? htmlspecialchars($_POST['question_text']) : ''; ?></textarea>
</div>
<div class="form-group">
<label for="question_type">Question Type <span class="text-danger">*</span></label>
<select class="form-control" id="question_type" name="question_type" required>
<option value="single_choice" <?php echo (isset($_POST['question_type']) && $_POST['question_type'] === 'single_choice') ? 'selected' : ''; ?>>Single Choice</option>
<option value="multiple_choice" <?php echo (isset($_POST['question_type']) && $_POST['question_type'] === 'multiple_choice') ? 'selected' : ''; ?>>Multiple Choice</option>
<option value="text" <?php echo (isset($_POST['question_type']) && $_POST['question_type'] === 'text') ? 'selected' : ''; ?>>Text Answer</option>
</select>
</div>
<div class="form-group">
<label for="marks">Marks <span class="text-danger">*</span></label>
<input type="number" class="form-control" id="marks" name="marks" value="<?php echo isset($_POST['marks']) ? $_POST['marks'] : '1'; ?>" min="1" required>
</div>
<div id="options-container" class="<?php echo (isset($_POST['question_type']) && $_POST['question_type'] === 'text') ? 'd-none' : ''; ?>">
<label>Options <span class="text-danger">*</span></label>
<p class="text-muted">Check the correct answer(s)</p>
<div class="options">
<?php for ($i = 0; $i < 4; $i++): ?>
<div class="form-row mb-2 option-row">
<div class="col-auto">
<div class="form-check mt-2">
<input class="form-check-input correct-answer" type="checkbox" name="correct_answers[]" value="<?php echo $i; ?>" <?php echo (isset($_POST['correct_answers']) && in_array($i, $_POST['correct_answers'])) ? 'checked' : ''; ?>>
</div>
</div>
<div class="col">
<input type="text" class="form-control" name="options[<?php echo $i; ?>]" placeholder="Option <?php echo $i + 1; ?>" value="<?php echo isset($_POST['options'][$i]) ? htmlspecialchars($_POST['options'][$i]) : ''; ?>">
</div>
<div class="col-auto">
<button type="button" class="btn btn-danger remove-option">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<?php endfor; ?>
</div>
<button type="button" class="btn btn-sm btn-info mt-2" id="add-option">
<i class="fas fa-plus"></i> Add Option
</button>
</div>
<input type="hidden" name="add_question" value="1">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save Question</button>
</form>
</div>
</div>
</div>
</div>
<!-- View Question Modal -->
<div class="modal fade" id="viewQuestionModal" tabindex="-1" role="dialog" aria-labelledby="viewQuestionModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="viewQuestionModalLabel">Question Details</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="question-details">
<!-- Question details will be loaded here via AJAX -->
<div class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Delete Question Modal -->
<div class="modal fade" id="deleteQuestionModal" tabindex="-1" role="dialog" aria-labelledby="deleteQuestionModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteQuestionModalLabel">Confirm Delete</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete this question? This action cannot be undone.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<form action="ajax/delete_question.php" method="POST" id="deleteQuestionForm">
<input type="hidden" name="question_id" id="delete_question_id" value="">
<input type="hidden" name="exam_id" value="<?php echo $exam_id; ?>">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
// Show/hide options based on question type
$('#question_type').change(function() {
if ($(this).val() === 'text') {
$('#options-container').addClass('d-none');
} else {
$('#options-container').removeClass('d-none');
// For single choice, ensure only one answer can be selected
if ($(this).val() === 'single_choice') {
$('.correct-answer').click(function() {
$('.correct-answer').not(this).prop('checked', false);
});
}
}
});
// Initialize single choice behavior
if ($('#question_type').val() === 'single_choice') {
$('.correct-answer').click(function() {
$('.correct-answer').not(this).prop('checked', false);
});
}
// Add option
$('#add-option').click(function() {
var optionCount = $('.option-row').length;
var newOption =
'<div class="form-row mb-2 option-row">' +
'<div class="col-auto">' +
'<div class="form-check mt-2">' +
'<input class="form-check-input correct-answer" type="checkbox" name="correct_answers[]" value="' + optionCount + '">' +
'</div>' +
'</div>' +
'<div class="col">' +
'<input type="text" class="form-control" name="options[' + optionCount + ']" placeholder="Option ' + (optionCount + 1) + '">' +
'</div>' +
'<div class="col-auto">' +
'<button type="button" class="btn btn-danger remove-option">' +
'<i class="fas fa-times"></i>' +
'</button>' +
'</div>' +
'</div>';
$('.options').append(newOption);
// Reinitialize single choice behavior
if ($('#question_type').val() === 'single_choice') {
$('.correct-answer').click(function() {
$('.correct-answer').not(this).prop('checked', false);
});
}
});
// Remove option
$(document).on('click', '.remove-option', function() {
if ($('.option-row').length > 2) {
$(this).closest('.option-row').remove();
} else {
alert('At least 2 options are required');
}
});
// View question
$('.view-question').click(function() {
var questionId = $(this).data('id');
$.ajax({
url: 'ajax/get_question_details.php',
type: 'GET',
data: { question_id: questionId },
success: function(response) {
$('#question-details').html(response);
$('#viewQuestionModal').modal('show');
},
error: function() {
alert('Failed to load question details');
}
});
});
// Delete question
$('.delete-question').click(function() {
var questionId = $(this).data('id');
$('#delete_question_id').val(questionId);
$('#deleteQuestionModal').modal('show');
});
});
</script>
<?php
// Include footer
include_once 'includes/footer.php';
?>