FIXED: Added a 'Send Assessment Invite' metabox to the Job edit screen. Includes metabox

This commit is contained in:
Ruben Ramirez 2025-04-03 20:24:33 -05:00
parent 772cbf6385
commit 53c5e2102f
2 changed files with 192 additions and 0 deletions

54
admin/js/job-metabox.js Normal file
View file

@ -0,0 +1,54 @@
/**
* Handles the "Send Invite" metabox functionality on the Job edit screen.
*/
(function($) {
'use strict';
$(document).ready(function() {
const $metabox = $('#quiztech_send_invite_metabox');
if (!$metabox.length) {
return; // Metabox not found
}
const $button = $metabox.find('#quiztech_send_invite_button');
const $emailInput = $metabox.find('#quiztech_applicant_email');
const $statusSpan = $metabox.find('#quiztech_invite_status');
$button.on('click', function() {
const email = $emailInput.val().trim();
// Basic email validation (more robust validation can be added)
if (!email || !/\S+@\S+\.\S+/.test(email)) {
$statusSpan.text('Please enter a valid email address.').css('color', 'red').show();
$emailInput.focus();
return;
}
// Disable button and show status
$button.prop('disabled', true);
$statusSpan.text(quiztechJobMetabox.sending_text).css('color', '').show();
// AJAX request
$.post(quiztechJobMetabox.ajax_url, {
action: 'quiztech_send_job_invite',
nonce: quiztechJobMetabox.nonce,
job_id: quiztechJobMetabox.job_id, // Passed via wp_localize_script
email: email
}, function(response) {
if (response.success) {
$statusSpan.text(response.data.message).css('color', 'green');
$emailInput.val(''); // Clear email field on success
} else {
const errorMsg = response.data && response.data.message ? response.data.message : 'Unknown error.';
$statusSpan.text(quiztechJobMetabox.error_text + ' ' + errorMsg).css('color', 'red');
}
}).fail(function() {
$statusSpan.text(quiztechJobMetabox.ajax_fail_text).css('color', 'red');
}).always(function() {
// Re-enable button
$button.prop('disabled', false);
});
});
});
})(jQuery);

138
src/Admin/JobMetaboxes.php Normal file
View file

@ -0,0 +1,138 @@
<?php
namespace Quiztech\AssessmentPlatform\Admin;
use Quiztech\AssessmentPlatform\Includes\Invitations;
/**
* Handles metaboxes for the Job CPT edit screen.
*/
class JobMetaboxes {
/**
* Register hooks for the metaboxes.
*/
public function register_hooks() {
add_action( 'add_meta_boxes', [ $this, 'add_send_invite_metabox' ] );
add_action( 'wp_ajax_quiztech_send_job_invite', [ $this, 'handle_send_invite_ajax' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_scripts' ] );
}
/**
* Adds the "Send Invite" metabox to the Job CPT.
*
* @param string $post_type The current post type.
*/
public function add_send_invite_metabox( $post_type ) {
if ( 'job' === $post_type ) {
add_meta_box(
'quiztech_send_invite_metabox', // Metabox ID
__( 'Send Assessment Invite', 'quiztech' ), // Title
[ $this, 'render_send_invite_metabox' ], // Callback function
'job', // Post type
'side', // Context (normal, side, advanced)
'high' // Priority (high, core, default, low)
);
}
}
/**
* Renders the HTML content for the "Send Invite" metabox.
*
* @param \WP_Post $post The current post object.
*/
public function render_send_invite_metabox( $post ) {
// Metabox HTML will go here (Step 5)
wp_nonce_field( 'quiztech_send_invite_action', 'quiztech_send_invite_nonce' );
?>
<p>
<label for="quiztech_applicant_email"><?php esc_html_e( 'Applicant Email:', 'quiztech' ); ?></label><br />
<input type="email" id="quiztech_applicant_email" name="quiztech_applicant_email" class="widefat" value="" />
</p>
<button type="button" id="quiztech_send_invite_button" class="button button-primary">
<?php esc_html_e( 'Send Invite', 'quiztech' ); ?>
</button>
<span id="quiztech_invite_status" style="margin-left: 10px; display: none;"></span>
<p class="description">
<?php esc_html_e( 'Sends an invitation to the applicant to complete the assessment linked to this job.', 'quiztech' ); ?>
</p>
<?php
}
/**
* Handles the AJAX request to send an invitation.
*/
public function handle_send_invite_ajax() {
// AJAX handler logic will go here (Step 6)
// Basic structure: check nonce, permissions, get data, call Invitations class, send response
check_ajax_referer( 'quiztech_send_invite_nonce_ajax', 'nonce' ); // Nonce sent via JS
if ( ! current_user_can( 'edit_post', isset( $_POST['job_id'] ) ? absint( $_POST['job_id'] ) : 0 ) ) {
wp_send_json_error( [ 'message' => __( 'Permission denied.', 'quiztech' ) ], 403 );
}
$job_id = isset( $_POST['job_id'] ) ? absint( $_POST['job_id'] ) : 0;
$applicant_email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : '';
if ( ! $job_id || ! is_email( $applicant_email ) ) {
wp_send_json_error( [ 'message' => __( 'Invalid Job ID or Email Address.', 'quiztech' ) ] );
}
// Get linked assessment ID
$assessment_id = get_post_meta( $job_id, '_quiztech_associated_assessment_id', true );
if ( empty( $assessment_id ) || 'assessment' !== get_post_type( $assessment_id ) ) {
wp_send_json_error( [ 'message' => __( 'No valid assessment linked to this job.', 'quiztech' ) ] );
}
$invitations = new Invitations();
$token_or_error = $invitations->create_invitation( $job_id, $assessment_id, $applicant_email );
if ( is_wp_error( $token_or_error ) ) {
wp_send_json_error( [ 'message' => $token_or_error->get_error_message() ] );
}
$token = $token_or_error;
$email_sent = $invitations->send_invitation_email( $applicant_email, $token, [ 'job_title' => get_the_title( $job_id ) ] ); // Pass job title
if ( $email_sent ) {
wp_send_json_success( [ 'message' => __( 'Invitation sent successfully!', 'quiztech' ) ] );
} else {
// Note: create_invitation succeeded, but email failed. Might want specific handling.
wp_send_json_error( [ 'message' => __( 'Invitation created, but email failed to send. Check SMTP settings.', 'quiztech' ) ] );
}
}
/**
* Enqueues admin scripts and styles for the Job edit screen.
*
* @param string $hook_suffix The current admin page hook.
*/
public function enqueue_admin_scripts( $hook_suffix ) {
// Script enqueue logic will go here (Step 7)
global $post_type;
if ( 'job' === $post_type && ( 'post.php' === $hook_suffix || 'post-new.php' === $hook_suffix ) ) {
$script_path = plugin_dir_url( QUIZTECH_PLUGIN_FILE ) . 'admin/js/job-metabox.js';
$script_asset_path = plugin_dir_path( QUIZTECH_PLUGIN_FILE ) . 'admin/js/job-metabox.asset.php';
$script_asset = file_exists( $script_asset_path ) ? require( $script_asset_path ) : [ 'dependencies' => [], 'version' => filemtime( plugin_dir_path( QUIZTECH_PLUGIN_FILE ) . $script_path ) ];
wp_enqueue_script(
'quiztech-job-metabox-script',
$script_path,
array_merge( $script_asset['dependencies'], [ 'jquery' ] ), // Add jquery dependency
$script_asset['version'],
true // Load in footer
);
// Pass data to the script
wp_localize_script( 'quiztech-job-metabox-script', 'quiztechJobMetabox', [
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'quiztech_send_invite_nonce_ajax' ),
'job_id' => get_the_ID(), // Get current post ID
'sending_text' => __( 'Sending...', 'quiztech' ),
'error_text' => __( 'Error:', 'quiztech' ),
'ajax_fail_text' => __( 'AJAX request failed.', 'quiztech' ),
]);
}
}
}