332 lines
No EOL
19 KiB
PHP
332 lines
No EOL
19 KiB
PHP
<?php
|
|
/**
|
|
* Template Name: Manage Questions
|
|
*
|
|
* This template is used for the page where Quiz Managers can manage Questions in the library.
|
|
*
|
|
* @package Quiztech
|
|
*/
|
|
|
|
// Ensure the user is logged in and has the appropriate capability.
|
|
// Capability required to manage questions.
|
|
$required_capability = 'edit_questions'; // Corresponds to 'question' CPT capability_type
|
|
|
|
if ( ! is_user_logged_in() || ! current_user_can( $required_capability ) ) {
|
|
// Redirect to login page or show an error message.
|
|
wp_safe_redirect( wp_login_url( get_permalink() ) );
|
|
exit;
|
|
// Alternatively, display an error message:
|
|
// wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'quiztech' ), 403 );
|
|
}
|
|
|
|
// Define available question types (Ideally, fetch this dynamically from the plugin)
|
|
$question_types = [
|
|
'text' => \__( 'Text (Single Line)', 'quiztech' ),
|
|
'textarea' => \__( 'Text Area (Multi-line)', 'quiztech' ),
|
|
'multiple-choice' => \__( 'Multiple Choice (Single Answer)', 'quiztech' ),
|
|
'checkbox' => \__( 'Checkboxes (Multiple Answers)', 'quiztech' ),
|
|
'numeric' => \__( 'Numeric', 'quiztech' ),
|
|
];
|
|
// TODO: Refactor this to use a plugin helper function or filter to avoid duplication.
|
|
|
|
get_header(); ?>
|
|
|
|
<div id="primary" class="content-area">
|
|
<main id="main" class="site-main">
|
|
|
|
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
|
|
<header class="entry-header">
|
|
<?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
|
|
</header><!-- .entry-header -->
|
|
|
|
<div class="entry-content">
|
|
|
|
<p><button id="quiztech-add-new-question-btn" class="button"><?php esc_html_e( 'Add New Question', 'quiztech' ); ?></button></p>
|
|
|
|
<div id="quiztech-add-edit-question-form" style="display: none; border: 1px solid #ccc; padding: 15px; margin-bottom: 20px;">
|
|
<h3><?php esc_html_e( 'Add/Edit Question', 'quiztech' ); ?></h3>
|
|
<p style="font-weight: bold;"><?php esc_html_e( 'Credits:', 'quiztech' ); ?> 3</p> <?php // TODO: Make credit cost dynamic ?>
|
|
|
|
<form id="question-form">
|
|
<?php wp_nonce_field( 'quiztech_save_question_action', 'quiztech_question_nonce' ); ?>
|
|
<input type="hidden" id="quiztech-question-id" name="question_id" value="">
|
|
|
|
<p>
|
|
<label for="quiztech-question-title"><?php esc_html_e( 'Question Title (for reference):', 'quiztech' ); ?></label><br>
|
|
<input type="text" id="quiztech-question-title" name="question_title" class="widefat" required>
|
|
</p>
|
|
|
|
<p>
|
|
<label for="quiztech-question-content"><?php esc_html_e( 'Question Text:', 'quiztech' ); ?></label><br>
|
|
<textarea id="quiztech-question-content" name="question_content" class="widefat" rows="4" required></textarea>
|
|
</p>
|
|
|
|
<p>
|
|
<label for="quiztech-question-type"><?php esc_html_e( 'Question Type:', 'quiztech' ); ?></label><br>
|
|
<select id="quiztech-question-type" name="question_type" required>
|
|
<option value=""><?php esc_html_e( '-- Select Type --', 'quiztech' ); ?></option>
|
|
<?php foreach ( $question_types as $value => $label ) : ?>
|
|
<option value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $label ); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</p>
|
|
|
|
<p id="quiztech-question-options-wrapper" style="display: none;">
|
|
<label for="quiztech-question-options"><?php esc_html_e( 'Options (one per line, mark correct with *):', 'quiztech' ); ?></label><br>
|
|
<textarea id="quiztech-question-options" name="question_options" class="widefat" rows="5"></textarea>
|
|
<small><?php esc_html_e('Example: Option A*'); ?></small> <?php // TODO: Clarify correct answer format for checkboxes ?>
|
|
</p>
|
|
|
|
<p>
|
|
<label for="quiztech-question-category"><?php esc_html_e( 'Category:', 'quiztech' ); ?></label><br>
|
|
<?php
|
|
wp_dropdown_categories( array(
|
|
'taxonomy' => 'quiztech_category',
|
|
'name' => 'question_category',
|
|
'id' => 'quiztech-question-category',
|
|
'show_option_none'=> __( '-- Select Category --', 'quiztech' ),
|
|
'hide_empty' => 0,
|
|
'hierarchical' => 1,
|
|
) );
|
|
?>
|
|
</p> <?php // Closing </p> was missing here ?>
|
|
|
|
<p>
|
|
<label for="quiztech-question-points"><?php esc_html_e( 'Question Points:', 'quiztech' ); ?></label><br>
|
|
<input type="number" id="quiztech-question-points" name="question_points" class="small-text" min="0" step="1" value="1">
|
|
<small><?php esc_html_e('Points awarded for a correct answer.', 'quiztech'); ?></small>
|
|
</p>
|
|
|
|
<?php // Removed extra closing </p> tag from line 97 of original ?>
|
|
|
|
<p>
|
|
<button type="submit" class="button button-primary"><?php esc_html_e( 'Save Question', 'quiztech' ); ?></button>
|
|
<button type="button" id="quiztech-cancel-edit-question-btn" class="button" style="display: none;"><?php esc_html_e( 'Cancel', 'quiztech' ); ?></button>
|
|
</p>
|
|
</form>
|
|
</div>
|
|
|
|
<h2><?php esc_html_e( 'Question Library', 'quiztech' ); ?></h2>
|
|
|
|
<?php
|
|
$args = array(
|
|
'post_type' => 'question',
|
|
'post_status' => 'publish', // Or 'any'
|
|
'posts_per_page' => 20, // Add pagination later
|
|
'orderby' => 'title',
|
|
'order' => 'ASC',
|
|
);
|
|
$questions_query = new WP_Query( $args );
|
|
?>
|
|
|
|
<?php if ( $questions_query->have_posts() ) : ?>
|
|
<table class="wp-list-table widefat fixed striped">
|
|
<thead>
|
|
<tr>
|
|
<th><?php esc_html_e( 'Title', 'quiztech' ); ?></th>
|
|
<th><?php esc_html_e( 'Type', 'quiztech' ); ?></th>
|
|
<th><?php esc_html_e( 'Category', 'quiztech' ); ?></th>
|
|
<th><?php esc_html_e( 'Actions', 'quiztech' ); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php while ( $questions_query->have_posts() ) : $questions_query->the_post(); ?>
|
|
<?php
|
|
$question_id = get_the_ID();
|
|
$q_type_value = get_post_meta( $question_id, '_quiztech_question_type', true );
|
|
// Use the updated $question_types array for display
|
|
$q_type_label = isset( $question_types[ $q_type_value ] ) ? $question_types[ $q_type_value ] : esc_html( $q_type_value );
|
|
$terms = get_the_terms( $question_id, 'quiztech_category' );
|
|
$category_name = ! empty( $terms ) && ! is_wp_error( $terms ) ? esc_html( $terms[0]->name ) : __( 'N/A', 'quiztech' );
|
|
?>
|
|
<tr>
|
|
<td><?php the_title(); ?></td>
|
|
<td><?php echo esc_html( $q_type_label ); ?></td>
|
|
<td><?php echo esc_html( $category_name ); ?></td>
|
|
<td>
|
|
<button class="button quiztech-edit-question-btn" data-question-id="<?php echo esc_attr( $question_id ); ?>"><?php esc_html_e( 'Edit', 'quiztech' ); ?></button>
|
|
<button class="button quiztech-delete-question-btn" data-question-id="<?php echo esc_attr( $question_id ); ?>"><?php esc_html_e( 'Delete', 'quiztech' ); ?></button>
|
|
<?php // Add nonces and JS handlers later ?>
|
|
</td>
|
|
</tr>
|
|
<?php endwhile; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php wp_reset_postdata(); // Restore original Post Data ?>
|
|
<?php // Add pagination links here later ?>
|
|
<?php else : ?>
|
|
<p><?php esc_html_e( 'No questions found in the library.', 'quiztech' ); ?></p>
|
|
<?php endif; ?>
|
|
|
|
<script>
|
|
jQuery(document).ready(function($) {
|
|
const formWrapper = $('#quiztech-add-edit-question-form');
|
|
const formElement = $('#question-form');
|
|
const formTitle = formWrapper.find('h3');
|
|
const questionIdField = $('#quiztech-question-id');
|
|
const cancelButton = $('#quiztech-cancel-edit-question-btn');
|
|
const submitButton = formElement.find('button[type="submit"]');
|
|
const tableBody = $('.wp-list-table tbody'); // Assuming table exists
|
|
|
|
// --- Helper: Reset and Hide Form ---
|
|
function resetAndHideForm() {
|
|
formElement[0].reset();
|
|
$('#quiztech-question-points').val('1'); // Reset points to default
|
|
questionIdField.val('');
|
|
cancelButton.hide();
|
|
formTitle.text('<?php echo esc_js( __( 'Add New Question', 'quiztech' ) ); ?>');
|
|
formWrapper.slideUp();
|
|
submitButton.prop('disabled', false).text('<?php echo esc_js( __( 'Save Question', 'quiztech' ) ); ?>');
|
|
// Clear any previous messages
|
|
formWrapper.find('.notice').remove();
|
|
$('#quiztech-question-type').trigger('change'); // Reset options visibility
|
|
}
|
|
|
|
// --- Helper: Display Form Message ---
|
|
function displayFormMessage(message, type = 'error') {
|
|
formWrapper.find('.notice').remove(); // Remove old messages
|
|
const noticeClass = type === 'success' ? 'notice-success' : 'notice-error';
|
|
// Insert message before the form element itself
|
|
formElement.before(`<div class="notice ${noticeClass} is-dismissible" style="margin-bottom: 10px; margin-top: 5px;"><p>${message}</p></div>`);
|
|
// Make dismissible work
|
|
$(document).on('click', '.notice.is-dismissible .notice-dismiss', function() {
|
|
$(this).closest('.notice').remove();
|
|
});
|
|
}
|
|
|
|
// --- Add New Button ---
|
|
$('#quiztech-add-new-question-btn').on('click', function() {
|
|
resetAndHideForm();
|
|
formWrapper.slideDown(); // Use slideDown instead of toggle for consistency
|
|
formTitle.text('<?php echo esc_js( __( 'Add New Question', 'quiztech' ) ); ?>');
|
|
});
|
|
|
|
// --- Cancel Button ---
|
|
cancelButton.on('click', function() {
|
|
resetAndHideForm();
|
|
});
|
|
|
|
// --- Type Change (Show/Hide Options) ---
|
|
$('#quiztech-question-type').on('change', function() {
|
|
const type = $(this).val();
|
|
// CORRECTED: Show options for multiple-choice and checkbox
|
|
if (type === 'multiple-choice' || type === 'checkbox') {
|
|
$('#quiztech-question-options-wrapper').show();
|
|
} else {
|
|
$('#quiztech-question-options-wrapper').hide();
|
|
}
|
|
}).trigger('change');
|
|
|
|
// --- Edit Button Click ---
|
|
// Use event delegation for dynamically added rows later if needed
|
|
tableBody.on('click', '.quiztech-edit-question-btn', function() {
|
|
const questionId = $(this).data('question-id');
|
|
const button = $(this);
|
|
button.prop('disabled', true).text('<?php echo esc_js( __( 'Loading...', 'quiztech' ) ); ?>');
|
|
formWrapper.find('.notice').remove(); // Clear previous messages
|
|
|
|
$.ajax({
|
|
url: quiztechThemeData.ajax_url,
|
|
type: 'POST',
|
|
data: {
|
|
action: 'quiztech_get_question',
|
|
nonce: quiztechThemeData.get_question_nonce,
|
|
question_id: questionId
|
|
},
|
|
dataType: 'json', // Expect JSON response
|
|
success: function(response) {
|
|
if (response.success) {
|
|
const data = response.data;
|
|
questionIdField.val(data.id);
|
|
$('#quiztech-question-title').val(data.title);
|
|
$('#quiztech-question-content').val(data.content);
|
|
$('#quiztech-question-type').val(data.type).trigger('change'); // Trigger change to show/hide options
|
|
$('#quiztech-question-options').val(data.options);
|
|
$('#quiztech-question-category').val(data.category);
|
|
$('#quiztech-question-points').val(data.points || 1); // Populate points, default to 1 if not set
|
|
|
|
formTitle.text('<?php echo esc_js( __( 'Edit Question', 'quiztech' ) ); ?>');
|
|
cancelButton.show();
|
|
formWrapper.slideDown();
|
|
// Scroll to form
|
|
$('html, body').animate({ scrollTop: formWrapper.offset().top - 50 }, 300);
|
|
} else {
|
|
alert(response.data.message || quiztechThemeData.error_generic);
|
|
}
|
|
},
|
|
error: function(jqXHR, textStatus, errorThrown) {
|
|
console.error("AJAX Error:", textStatus, errorThrown, jqXHR.responseText);
|
|
alert(quiztechThemeData.error_generic);
|
|
},
|
|
complete: function() {
|
|
button.prop('disabled', false).text('<?php echo esc_js( __( 'Edit', 'quiztech' ) ); ?>');
|
|
}
|
|
});
|
|
});
|
|
|
|
// --- Delete Button Click --- (Needs AJAX implementation)
|
|
tableBody.on('click', '.quiztech-delete-question-btn', function() {
|
|
const questionId = $(this).data('question-id');
|
|
const button = $(this);
|
|
const row = button.closest('tr');
|
|
|
|
if (confirm('<?php echo esc_js( __( 'Are you sure you want to delete this question?', 'quiztech' ) ); ?>')) {
|
|
alert('Delete functionality for question ID ' + questionId + ' needs AJAX implementation (nonce, handler, etc.).');
|
|
// TODO: AJAX call to delete question (needs nonce and handler)
|
|
// Example:
|
|
// $.ajax({
|
|
// url: quiztechThemeData.ajax_url,
|
|
// type: 'POST',
|
|
// data: { action: 'quiztech_delete_question', nonce: '...', question_id: questionId },
|
|
// success: function(response) { if(response.success) { row.fadeOut(300, function() { $(this).remove(); }); } else { alert(response.data.message); } },
|
|
// error: function() { alert(quiztechThemeData.error_generic); }
|
|
// });
|
|
}
|
|
});
|
|
|
|
// --- Form Submission ---
|
|
formElement.on('submit', function(e) {
|
|
e.preventDefault();
|
|
submitButton.prop('disabled', true).text('<?php echo esc_js( __( 'Saving...', 'quiztech' ) ); ?>');
|
|
formWrapper.find('.notice').remove(); // Clear previous messages
|
|
|
|
const formData = $(this).serialize(); // Includes nonce and all fields
|
|
|
|
$.ajax({
|
|
url: quiztechThemeData.ajax_url,
|
|
type: 'POST',
|
|
data: formData + '&action=quiztech_save_question', // Add action parameter
|
|
dataType: 'json', // Expect JSON response
|
|
success: function(response) {
|
|
if (response.success) {
|
|
// Display success message within the form area before hiding/reloading
|
|
displayFormMessage(response.data.message, 'success');
|
|
// Option 1: Reload page after delay
|
|
setTimeout(function() { location.reload(); }, 1500);
|
|
// Option 2: Reset and hide form (if table update was dynamic)
|
|
// resetAndHideForm();
|
|
// TODO: Update table dynamically
|
|
} else {
|
|
displayFormMessage(response.data.message || quiztechThemeData.error_generic, 'error');
|
|
submitButton.prop('disabled', false).text('<?php echo esc_js( __( 'Save Question', 'quiztech' ) ); ?>');
|
|
}
|
|
},
|
|
error: function(jqXHR, textStatus, errorThrown) {
|
|
console.error("AJAX Error:", textStatus, errorThrown, jqXHR.responseText);
|
|
displayFormMessage(quiztechThemeData.error_generic, 'error');
|
|
submitButton.prop('disabled', false).text('<?php echo esc_js( __( 'Save Question', 'quiztech' ) ); ?>');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|
|
</div><!-- .entry-content -->
|
|
|
|
</article><!-- #post-<?php the_ID(); ?> -->
|
|
|
|
</main><!-- #main -->
|
|
</div><!-- #primary -->
|
|
|
|
<?php
|
|
get_footer();
|