Files
SIGE-WEB-snapshot/wp-content/plugins/sige-events/includes/enrollments.php

1346 lines
66 KiB
PHP

<?php
function frontendEnrollmentControlGeneric($attributes)
{
nocache_headers();
// Append nocache query parameter to bust cache
if (!isset($_GET['nocache'])) {
$new_url = add_query_arg('nocache', time(), get_permalink());
wp_redirect($new_url);
exit();
}
// Prevent back/forward navigation cache
$output = '<script>
if (performance.navigation.type === performance.navigation.TYPE_BACK_FORWARD) {
window.location.reload();
}
</script>';
if (!is_user_logged_in()) {
// Add the style to the head section of the page
return '<p>You need to be logged in to view this page.</p>';
}
$user = wp_get_current_user();
$roles = $user->roles;
$args = shortcode_atts(array('activity_id' => 'none', 'allowed_role' => 'none'), $attributes);
$allowed_role = $args['allowed_role'];
$has_access = array($allowed_role, 'administrator');
$user_allowed_roles = array_intersect($roles, $has_access);
if (empty($user_allowed_roles)) {
// Add the style for the restricted message
return '
<p>Sorry, you don\'t have permission to view this content.</p>
';
} else {
global $wpdb;
//$current_user = wp_get_current_user();
$user_id = $user->ID;
$activity_id = intval($args['activity_id']);
// Define the additional meta keys
$additional_meta_keys = [
'forca',
'full_name',
'posto',
'militar',
'instituição',
'nacionalidade',
'efetivo_dcta',
'cidade',
'estado',
'areaatividadeprincipal',
'setordeatuacao',
'cargofuncao',
'ehativa',
'circulo_hierarquico',
'pais',
'formacao_academica',
'regiao_do_brasil',
'genero'
];
// Handle saving additional features selection
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['additional_features_applied'])) {
$selected_meta_keys = isset($_POST['additional_features']) ? array_intersect($additional_meta_keys, $_POST['additional_features']) : [];
update_user_meta($user_id, 'selected_additional_features_frontend', $selected_meta_keys);
// Redirect to avoid resubmission
wp_safe_redirect(add_query_arg([], wp_get_referer()));
exit;
} else {
$selected_meta_keys = get_user_meta($user_id, 'selected_additional_features_frontend', true);
if (!$selected_meta_keys) {
$selected_meta_keys = ['full_name', 'militar', 'posto', 'instituição', 'nacionalidade', 'efetivo_dcta'];
}
}
// Handle form submission for updating enrollment status
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['apply_status']) && isset($_POST['selected_enrollments'])) {
$new_status = sanitize_text_field($_POST['new_status']);
$selected_enrollments = array_map('intval', $_POST['selected_enrollments']);
if (!empty($selected_enrollments)) {
foreach ($selected_enrollments as $enrollment_id) {
$wpdb->update(
"{$wpdb->prefix}sige_enrollments",
['status' => $new_status],
['id' => $enrollment_id]
);
$enrollment_data = $wpdb->get_row(
$wpdb->prepare("
SELECT user_id, activity_id
FROM {$wpdb->prefix}sige_enrollments
WHERE id = %d", $enrollment_id)
);
send_email_notification($enrollment_data->user_id, $new_status, $enrollment_data->activity_id);
usleep(100_000);
}
// Redirect to the same page to clear POST data
wp_safe_redirect(add_query_arg([], wp_get_referer()));
exit;
} else {
echo '<div class="notice notice-error"><p>Please select at least one enrollment.</p></div>';
}
}
// Fetch summary counts
$summary_counts = $wpdb->get_results("
SELECT
a.name as activity_name,
a.slots,
COUNT(e.id) as total_requests,
SUM(CASE WHEN e.status = 'Enrollment Canceled by User' THEN 1 ELSE 0 END) as canceled_by_user,
SUM(CASE WHEN e.status = 'Waiting List' THEN 1 ELSE 0 END) as waiting_list,
SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as approved,
SUM(CASE WHEN e.status = 'Not Approved' THEN 1 ELSE 0 END) as not_approved,
SUM(CASE WHEN e.status = 'Under Analysis' THEN 1 ELSE 0 END) as under_analysis,
a.slots - SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as available_slots
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE a.id = $activity_id
GROUP BY a.name, a.slots
");
ob_start();
$unique_id = uniqid('sige_');
//sige_enqueue_export_csv_script($unique_id);
// Display summary counts table
echo '<h3>Enrollment Summary</h3>';
echo '<table id="summary-table-' . $unique_id . '" class="display" style="width: 100%; margin: 0; padding: 0;">
<thead>
<tr>
<th>Activity Name</th>
<th>Enrollment Canceled by User</th>
<th>Waiting List</th>
<th>Approved</th>
<th>Not Approved</th>
<th>Under Analysis</th>
<th>Total Enrollment Requests</th>
<th>Enrollment Availables</th>
<th>Slots</th>
</tr>
</thead>
<tbody>';
if ($summary_counts) {
foreach ($summary_counts as $summary) {
echo '<tr>
<td>' . esc_html($summary->activity_name) . '</td>
<td>' . esc_html($summary->canceled_by_user) . '</td>
<td>' . esc_html($summary->waiting_list) . '</td>
<td>' . esc_html($summary->approved) . '</td>
<td>' . esc_html($summary->not_approved) . '</td>
<td>' . esc_html($summary->under_analysis) . '</td>
<td>' . esc_html($summary->total_requests) . '</td>
<td>' . esc_html($summary->available_slots) . '</td>
<td>' . esc_html($summary->slots) . '</td>
</tr>';
}
} else {
echo '<tr><td colspan="9" style="text-align: center;">No data found</td></tr>';
}
echo '</tbody></table>';
// Fetch enrollments with additional meta data if selected
$meta_selects = '';
$meta_joins = '';
foreach ($selected_meta_keys as $meta_key) {
$meta_selects .= ", um_$meta_key.meta_value as $meta_key";
$meta_joins .= " LEFT JOIN {$wpdb->prefix}usermeta um_$meta_key ON um_$meta_key.user_id = u.ID AND um_$meta_key.meta_key = '$meta_key'";
}
$query = $wpdb->prepare("
SELECT e.*, a.name as activity_name, u.user_email $meta_selects
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
$meta_joins
WHERE a.id = %d
ORDER BY e.enrollment_date ASC
", $activity_id);
$enrollments = $wpdb->get_results($query);
// Display additional features form
echo '<div class="additional-features-container" style="display: flex; align-items: center; margin-bottom: 20px;">';
echo '<h3 style="margin: 0;">Additional Features</h3>';
echo '<button id="toggle-features" class="button button-secondary" style="margin-left: 10px;">Expand Features</button>';
echo '</div>';
echo '<div id="features-container" style="display: none; width: 100%; margin-top: 20px;">';
echo '<form method="post" action="" style="width: 100%;">';
foreach ($additional_meta_keys as $meta_key) {
$checked = in_array($meta_key, $selected_meta_keys) ? 'checked' : '';
echo '<label style="display: block; margin-bottom: 10px;"><input type="checkbox" name="additional_features[]" value="' . $meta_key . '" ' . $checked . '> ' . ucfirst(str_replace('_', ' ', $meta_key)) . '</label>';
}
echo '<input type="hidden" name="additional_features_applied" value="1">';
echo '<input type="submit" value="Apply" class="button button-primary" style="margin-top: 20px;">';
echo '</form>';
echo '</div>';
// Display the enrollments table
echo '<h3>Existing Enrollments</h3>';
echo '<div style="width: 100%; margin: 0; padding: 0;">';
echo '<form method="post" action="" style="width: 100%; margin: 0; padding: 0;">';
echo '<input type="hidden" id="selected-meta-keys" value="' . esc_attr(json_encode(array_values($selected_meta_keys))) . '">';
echo '<button id="export-csv" type="button" class="button button-secondary" style="margin-bottom: 20px;">Export to CSV</button>';
echo '<table id="enrollments-table' . $unique_id . '" class="display" style="width: 100%; margin: 0; padding: 0;">
<thead>
<tr>
<th style="text-align: center;"><input type="checkbox" id="select_all"> Select All</th>
<th>Activity Name</th>
<th>User ID</th>
<th>User Email</th>
<th>Enrollment Date</th>
<th>Status</th>';
foreach ($selected_meta_keys as $meta_key) {
echo '<th>' . ucfirst(str_replace('_', ' ', $meta_key)) . '</th>';
}
echo '</tr></thead><tbody>';
if ($enrollments) {
foreach ($enrollments as $enrollment) {
$row_style = '';
$checkbox_disabled = '';
if ($enrollment->status == 'Enrollment Canceled by User') {
$row_style = 'style="background-color: #f38d8d;"';
$checkbox_disabled = 'disabled';
} elseif ($enrollment->status == 'Waiting List') {
$row_style = 'style="background-color: #e3db69;"';
} elseif ($enrollment->status == 'Approved') {
$row_style = 'style="background-color: #33ff7a;"';
} elseif ($enrollment->status == 'Not Approved') {
$row_style = 'style="background-color: #bc97cd;"';
} elseif ($enrollment->status == 'Under Analysis') {
$row_style = 'style="background-color: #5ecac7;"';
}
$formatted_date = date('d-m-Y', strtotime($enrollment->enrollment_date));
echo "<tr $row_style>
<td style='text-align: center;'><input type='checkbox' class='select-enrollment' name='selected_enrollments[]' value='{$enrollment->id}' $checkbox_disabled></td>
<td style='font-weight: bold;'>{$enrollment->activity_name}</td>
<td style='font-weight: bold;'>{$enrollment->user_id}</td>
<td style='font-weight: bold;'>{$enrollment->user_email}</td>
<td style='font-weight: bold;'>$formatted_date</td>
<td style='font-weight: bold;'>{$enrollment->status}</td>";
foreach ($selected_meta_keys as $meta_key) {
echo '<td style="font-weight: bold;">' . esc_html($enrollment->$meta_key) . '</td>';
}
echo '</tr>';
}
} else {
$colspan = 6 + count($selected_meta_keys); // 6 base columns + dynamic meta columns
echo '<tr><td colspan="' . $colspan . '" style="text-align: center;">No enrollments found</td></tr>';
}
echo '</tbody></table>';
if ($enrollments) {
echo '<div style="margin-top: 20px;">
<select name="new_status" required>
<option value="" disabled selected>Select status</option>
<option value="Waiting List">Waiting List</option>
<option value="Not Approved">Not Approved</option>
<option value="Approved">Approved</option>
</select>
<input type="submit" name="apply_status" value="Apply" class="button button-primary">';
echo '</div>';
}
echo '</form>';
echo '</div>';
// Add the color legend
echo '<div style="margin-top: 20px; display: flex; align-items: center;">
<h3 style="margin-right: 20px;">Legend:</h3>';
echo '<div style="display: flex; flex-wrap: wrap; gap: 10px;">
<span style="background-color: #f38d8d; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Enrollment Canceled by User</span>
<span style="background-color: #33ff7a; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Approved</span>
<span style="background-color: #e3db69; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Waiting List</span>
<span style="background-color: #bc97cd; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Not Approved</span>
<span style="background-color: #5ecac7; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Under Analysis</span>
</div></div>';
echo '<script>
jQuery(document).ready(function($) {
$("#summary-table-' . $unique_id . '").DataTable({
"paging": false,
"searching": false,
"info": false,
"scrollX": true,
"autoWidth": true
});
$("#enrollments-table' . $unique_id . '").DataTable({
"scrollX": true,
"autoWidth": true,
"pageLength": 50, // Set the default number of entries to show
"lengthMenu": [ [10, 25, 50, 100, 200, 500, -1], [10, 25, 50, 100, 200, 500, "All"] ] // Add custom options for the number of entries
});
$("#select_all").click(function() {
$("input[type=checkbox].select-enrollment").each(function() {
if (!$(this).is(":disabled")) {
$(this).prop("checked", $("#select_all").prop("checked"));
}
});
});
$("#toggle-features").click(function() {
$("#features-container").slideToggle();
$(this).text(function(i, text){
return text === "Expand Features" ? "Collapse Features" : "Expand Features";
});
});
$("#export-csv").click(function(e) {
e.preventDefault();
const selectedMetaKeys = JSON.parse($("#selected-meta-keys").val());
const now = new Date();
const formattedDate = `${("0" + now.getDate()).slice(-2)}_${("0" + (now.getMonth() + 1)).slice(-2)}_${now.getFullYear()}_${("0" + now.getHours()).slice(-2)}_${("0" + now.getMinutes()).slice(-2)}_${("0" + now.getSeconds()).slice(-2)}`;
const filename = `enrollments_${formattedDate}.csv`;
let csvContent = "data:text/csv;charset=utf-8,";
csvContent += "Activity Name,User ID,User Email,Enrollment Date,Status";
// Add selected meta keys to CSV header
if (selectedMetaKeys.length > 0) {
selectedMetaKeys.forEach(function(metaKey) {
csvContent += "," + metaKey.charAt(0).toUpperCase() + metaKey.slice(1).replace(/_/g, " ");
});
}
csvContent += "\n";
$("#enrollments-table' . $unique_id . ' tbody tr").each(function() {
const row = $(this);
const activityName = row.find("td:nth-child(2)").text().trim();
const userID = row.find("td:nth-child(3)").text().trim();
const userEmail = row.find("td:nth-child(4)").text().trim();
const enrollmentDate = row.find("td:nth-child(5)").text().trim();
const status = row.find("td:nth-child(6)").text().trim();
let rowData = `${activityName},${userID},${userEmail},${enrollmentDate},${status}`;
if (selectedMetaKeys.length > 0) {
selectedMetaKeys.forEach(function(metaKey, index) {
rowData += "," + row.find("td:nth-child(" + (7 + index) + ")").text().trim();
});
}
csvContent += rowData + "\n";
});
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
});
</script>';
return ob_get_clean();
}
}
add_shortcode('genericEnrollmentControl', 'frontendEnrollmentControlGeneric');
/**
* Handles user enrollment for a specific activity via shortcode.
*
* @param array $attributes Shortcode attributes, expects 'activity_id'.
* @return string HTML output for enrollment status and form.
*/
function get_enrollment($attributes)
{
global $wpdb;
$user = wp_get_current_user();
$user_id = $user->ID;
$args = shortcode_atts(array('activity_id' => 'none', 'open' => 'yes'), $attributes);
$activity_id = $args['activity_id'];
$open_enrollment = $args['open'];
// Handle form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['activity_id']) && $_POST['activity_id'] == $activity_id) {
if (isset($_POST['enrollment_action'])) {
if ($_POST['enrollment_action'] === 'add') {
// Add or update enrollment to "Under Analysis"
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM {$wpdb->prefix}sige_enrollments WHERE activity_id = %d AND user_id = %d",
$activity_id,
$user_id
));
if ($existing) {
$wpdb->update(
"{$wpdb->prefix}sige_enrollments",
['status' => 'Under Analysis'],
['activity_id' => $activity_id, 'user_id' => $user_id]
);
send_email_notification($user_id, 'Under Analysis', $activity_id);
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_enrollments",
[
'activity_id' => $activity_id,
'user_id' => $user_id,
'enrollment_date' => current_time('mysql'),
'status' => 'Under Analysis'
]
);
send_email_notification($user_id, 'Under Analysis', $activity_id);
}
} elseif ($_POST['enrollment_action'] === 'cancel') {
// Cancel enrollment
$wpdb->update(
"{$wpdb->prefix}sige_enrollments",
['status' => 'Enrollment Canceled by User'],
['activity_id' => $activity_id, 'user_id' => $user_id]
);
send_email_notification($user_id, 'Enrollment Canceled by User', $activity_id);
}
$referer = wp_get_referer();
$safe_referer = wp_validate_redirect($referer, home_url());
wp_safe_redirect(home_url('/inscricoes/'));
exit;
}
}
// Fetch current status only if user is logged in
if (!$user_id) {
return '';
}
$enrollment = $wpdb->get_var($wpdb->prepare("
SELECT status FROM {$wpdb->prefix}sige_enrollments
WHERE activity_id = %d AND user_id = %d
", $activity_id, $user_id));
$headline = '<p>Você ainda não se inscreveu nesta atividade!</p><br>';
$button = '';
if ($enrollment) {
$headline = '<p>Status da sua inscrição: ' . esc_html($enrollment) . '</p><br>';
if ($enrollment !== 'Enrollment Canceled by User' && $enrollment !== 'Not Approved') {
$button =
'<form method="post" style="display:inline;">
<input type="hidden" name="activity_id" value="' . esc_attr($activity_id) . '">
<button type="submit" name="enrollment_action" value="cancel" style="background:#f44336;color:#fff;">Cancelar inscrição</button>
</form>';
}
} else if ($open_enrollment !== 'yes') {
$headline = '<p>Inscrições encerradas</p><br>';
}
if ($open_enrollment === 'yes' && (empty($enrollment) || $enrollment === 'Enrollment Canceled by User'))
$button =
'<form method="post">
<input type="hidden" name="activity_id" value="' . esc_attr($activity_id) . '">
<button type="submit" name="enrollment_action" value="add">Solicite sua inscrição</button>
</form>';
return $headline . ' ' . $button;
}
add_shortcode('get_enroll', 'get_enrollment');
function frontendAttendanceControl()
{
ob_start();
nocache_headers();
// Append nocache query parameter to bust cache
if (!isset($_GET['nocache'])) {
// Append a unique timestamp-based parameter to the URL
$permalink = get_permalink();
if (!$permalink) {
$permalink = home_url();
}
$new_url = add_query_arg('nocache', time(), $permalink);
wp_redirect($new_url);
exit;
exit();
}
if (!is_user_logged_in()) {
return '
<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #808080; /* Gray background */
color: #fff; /* White text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>You must be logged in to handle the attendance control.</p>
</div>';
}
// Check if the user has administrator or contributor role
if (!(current_user_can('administrator') || current_user_can('comissao_secretaria') || current_user_can('comissao_suporte')) && !current_user_can('contributor')) {
return '<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #e0e0e0; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); z-index: 999; text-align: center;">
<p>You do not have the required permissions to handle the attendance control.</p>
</div>';
}
// Handle form submission to update attendance
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['update_attendance'])) {
//error_log('******************************************');
//error_log('Form submitted with update_attendance');
$enrollment_id = isset($_POST['enrollment_id']) ? intval($_POST['enrollment_id']) : 0;
//error_log('enrollment_id: ' . $enrollment_id);
$attended = isset($_POST['attended']) ? sanitize_text_field($_POST['attended']) : '';
//error_log('attended: ' . $attended);
$user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
//error_log('user_id: ' . $user_id);
//$selected_activity = isset($_POST['selected_activity']) ? sanitize_text_field($_POST['selected_activity']) : 'All';
$selected_activity = sanitize_text_field($_POST['selected_activity']);
if ($enrollment_id && $attended) {
//error_log('Valid enrollment_id and attended values');
global $wpdb;
// Fetch the activity_id from the sige_enrollments table
$activity_id = $wpdb->get_var($wpdb->prepare("SELECT activity_id FROM {$wpdb->prefix}sige_enrollments WHERE id = %d", $enrollment_id));
//error_log('activity_id: ' . $activity_id);
$existing_record = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$wpdb->prefix}sige_enrollment_attendance_control WHERE enrollment_id = %d", $enrollment_id));
if ($existing_record) {
$wpdb->update(
"{$wpdb->prefix}sige_enrollment_attendance_control",
['attended' => $attended],
['id' => $existing_record]
);
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_enrollment_attendance_control",
[
'enrollment_id' => $enrollment_id,
'attended' => $attended
]
);
}
}
if ($activity_id !== null) {
// error_log('Sending email notification');
send_email_notification($user_id, $attended, $activity_id);
} else {
//error_log('Activity ID not found for enrollment ID ' . $enrollment_id);
}
} else {
$selected_activity = isset($_POST['selected_activity']) ? sanitize_text_field($_POST['selected_activity']) : 'SIGE XXVII';
//$selected_activity = sanitize_text_field($_POST['selected_activity']);
}
// Handle QR code verification
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['qr_scanner_used']) && $_POST['qr_scanner_used'] == '1') {
$hashed_user_id = sanitize_text_field($_POST['filtered_user_id']);
$filtered_user_id = verifyUserBasedOnQRCode($hashed_user_id);
} else {
$filtered_user_id = isset($_POST['filtered_user_id']) ? intval($_POST['filtered_user_id']) : '';
}
} else {
$filtered_user_id = '';
}
// Fetch enrollments with status "Approved/Waiting List" and modality "In-person or Hybrid"
global $wpdb;
$query = "
SELECT e.id as enrollment_id, e.activity_id, a.name as activity_name, e.user_id, um1.meta_value as full_name, u.user_email, e.enrollment_date, e.status, ac.attended
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
WHERE (e.status = 'Approved' OR e.status = 'Waiting List') AND (a.modality = 'In-person' OR a.modality = 'Hybrid')
";
if ($selected_activity !== 'All') {
$query .= $wpdb->prepare(" AND a.id = %d", $selected_activity);
}
if ($filtered_user_id) {
$query .= $wpdb->prepare(" AND e.user_id = %d", $filtered_user_id);
}
$enrollments = $wpdb->get_results($query);
$activities = $wpdb->get_results("SELECT id, name FROM {$wpdb->prefix}sige_activities WHERE modality IN ('In-person', 'Hybrid') AND YEAR(start_date) = YEAR(CURDATE());");
?>
<div class="wrap">
<h2>Attendance Control</h2>
<div style="background-color: #f0f0f0; padding: 20px; border-radius: 5px; margin-bottom: 20px; text-align: center;">
<div style="margin-bottom: 20px;">
<div id="qr-reader" style="width:300px; margin: 0 auto;"></div>
<button id="start-qr-reader" class="button button-secondary"
style="display: inline-block; margin-top: 10px; width: 300px;">Start QR Scanner</button>
</div>
<form method="post" action="" id="attendanceForm"
style="display: flex; flex-direction: column; gap: 10px; align-items: center;">
<input type="text" name="filtered_user_id" id="filtered_user_id" placeholder="Enter User ID"
value="<?php echo esc_attr($filtered_user_id); ?>" style="width: 300px;" />
<input type="hidden" name="qr_scanner_used" id="qr_scanner_used" value="0" />
<div style="display: flex; align-items: center; gap: 10px;">
<label for="activityFilter">Activity:</label>
<select id="activityFilter" name="selected_activity" form="attendanceForm">
<option value="All">All</option>
<?php foreach ($activities as $activity) { ?>
<option value="<?php echo esc_attr($activity->id); ?>" <?php selected($selected_activity, $activity->id); ?>><?php echo esc_html($activity->name); ?></option>
<?php } ?>
</select>
</div>
<input type="submit" value="Filter" class="button button-secondary" style="width: 300px;" />
</form>
</div>
<div style="background-color: #f0f0f0; padding: 20px; border-radius: 5px; overflow-x: auto; margin-bottom: 20px;">
<table id="attendanceTable" class="display" style="width:100%">
<thead>
<tr>
<th>Activity Name</th>
<th>User ID</th>
<th>User Full Name</th>
<th>Email</th>
<th>Enrollment Date</th>
<th>Status</th>
<th>Attended</th>
<th>Action</th>
</tr>
</thead>
<tbody id="tableBody">
<?php
if ($enrollments) {
foreach ($enrollments as $enrollment) {
?>
<tr data-attended="<?php echo esc_attr($enrollment->attended); ?>">
<td><?php echo esc_html($enrollment->activity_name); ?></td>
<td><?php echo esc_html($enrollment->user_id); ?></td>
<td><?php echo esc_html($enrollment->full_name); ?></td>
<td><?php echo esc_html($enrollment->user_email); ?></td>
<td><?php echo esc_html($enrollment->enrollment_date); ?></td>
<td><?php echo esc_html($enrollment->status); ?></td>
<td><?php echo esc_html($enrollment->attended); ?></td>
<td>
<form method="post" action="">
<input type="hidden" name="enrollment_id"
value="<?php echo esc_attr($enrollment->enrollment_id); ?>" />
<input type="hidden" name="user_id" value="<?php echo esc_attr($enrollment->user_id); ?>" />
<input type="hidden" name="selected_activity"
value="<?php echo esc_attr($selected_activity); ?>" />
<select name="attended">
<option value="yes" <?php selected($enrollment->attended, 'yes'); ?>>Yes</option>
<option value="no" <?php selected($enrollment->attended, 'no'); ?>>No</option>
</select>
<input type="submit" name="update_attendance" value="Update"
class="button button-primary" />
</form>
</td>
</tr>
<?php
}
} else {
?>
<tr>
<td colspan="8">No approved enrollments found.</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
<div style="background-color: #f0f0f0; padding: 20px; border-radius: 5px; text-align: center;">
<button id="export-csv" class="button button-secondary" style="margin-top: 10px;">Export to CSV</button>
</div>
</div>
<!-- Include DataTables JS and CSS -->
<script src="https://cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.24/js/dataTables.jqueryui.min.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.24/css/dataTables.jqueryui.min.css">
<script>
jQuery(document).ready(function($) {
function initializeQrCodeScanner() {
if (typeof Html5Qrcode !== "undefined") {
const qrReader = new Html5Qrcode("qr-reader");
const startQrReaderBtn = document.getElementById("start-qr-reader");
const userIdInput = document.getElementById("filtered_user_id");
const qrScannerUsedInput = document.getElementById("qr_scanner_used");
let qrScannerRunning = false;
startQrReaderBtn.addEventListener("click", function() {
if (!qrScannerRunning) {
qrReader.start({
facingMode: "environment"
}, {
fps: 10,
qrbox: 250
},
qrCodeMessage => {
userIdInput.value = qrCodeMessage;
qrScannerUsedInput.value = 1; // Set this to indicate scanner was used
qrReader.stop().then(() => {
qrScannerRunning = false;
startQrReaderBtn.textContent = "Start QR Scanner";
// Auto-submit the form after scanning the QR code
document.getElementById("attendanceForm").submit();
});
},
errorMessage => {
console.warn(`QR Code scanning error: ${errorMessage}`);
}
).then(() => {
qrScannerRunning = true;
startQrReaderBtn.textContent = "Stop QR Scanner";
}).catch(err => {
console.error(`Unable to start QR Code scanning: ${err}`);
});
} else {
qrReader.stop().then(() => {
qrScannerRunning = false;
startQrReaderBtn.textContent = "Start QR Scanner";
}).catch(err => {
console.error(`Unable to stop QR Code scanning: ${err}`);
});
}
});
} else {
console.error("Html5Qrcode library is not loaded properly.");
}
}
function exportToCsv(filename, rows) {
const processRow = function(row) {
let finalVal = '';
for (let j = 0; j < row.length; j++) {
let innerValue = row[j] === null ? '' : row[j].toString();
if (row[j] instanceof Date) {
innerValue = row[j].toLocaleString();
}
let result = innerValue.replace(/"/g, '""');
if (result.search(/("|,|\n)/g) >= 0)
result = '"' + result + '"';
if (j > 0)
finalVal += ';'; // Changed to semicolon
finalVal += result;
}
return finalVal + '\n';
};
let csvFile = '';
for (let i = 0; i < rows.length; i++) {
csvFile += processRow(rows[i]);
}
const blob = new Blob([csvFile], {
type: 'text/csv;charset=utf-8;'
});
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
const url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
function generateCsvFileName() {
const now = new Date();
const formattedDate = `${("0" + now.getDate()).slice(-2)}_${("0" + (now.getMonth() + 1)).slice(-2)}_${now.getFullYear()}_${("0" + now.getHours()).slice(-2)}_${("0" + now.getMinutes()).slice(-2)}_${("0" + now.getSeconds()).slice(-2)}`;
return `attendance_${formattedDate}.csv`;
}
document.getElementById('export-csv').addEventListener('click', function() {
const table = document.querySelector('#attendanceTable');
const rows = [];
rows.push(["Activity Name", "User ID", "User Full Name", "Email", "Enrollment Date", "Status", "Attended"]);
table.querySelectorAll('tbody tr').forEach(function(row) {
const rowData = [];
row.querySelectorAll('td').forEach(function(cell, index) {
if (index < 7) { // Exclude the last column (Action)
rowData.push(cell.innerText.trim());
}
});
rows.push(rowData);
});
exportToCsv(generateCsvFileName(), rows);
});
initializeQrCodeScanner();
// Initialize DataTables
$('#attendanceTable').DataTable({
paging: true,
searching: true,
lengthChange: true,
pageLength: -1,
autoWidth: false,
scrollX: true,
order: [
[2, 'asc']
],
lengthMenu: [
[10, 25, 50, 100, 200, 500, -1],
[10, 25, 50, 100, 200, 500, "All"]
], // Add custom options for the number of entries
language: {
lengthMenu: "Show _MENU_ entries",
info: "Showing _START_ to _END_ of _TOTAL_ entries",
infoFiltered: "(filtered from _MAX_ total entries)",
paginate: {
previous: "Previous",
next: "Next"
}
}
});
// Highlight rows based on "Attended" column value
$('#attendanceTable tbody tr').each(function() {
const attended = $(this).data('attended');
if (attended === 'yes') {
$(this).css('background-color', '#33ff7a');
} else if (attended === 'no') {
$(this).css('background-color', '#f54949');
}
});
});
</script>
<?php
return ob_get_clean();
}
add_shortcode('frontend_attendance_control', 'frontendAttendanceControl');
// Ensure the phpqrcode and tcpdf library are included
require_once plugin_dir_path(__FILE__) . '../phpqrcode/qrlib.php';
require_once plugin_dir_path(__FILE__) . '../tcpdf/tcpdf.php';
function frontendAttendanceControlAutomatic()
{
ob_start();
session_start(); // Start the session to store the success message
nocache_headers();
// Append nocache query parameter to bust cache
if (!isset($_GET['nocache'])) {
// Append a unique timestamp-based parameter to the URL
$permalink = get_permalink();
if (!$permalink) {
$permalink = home_url();
}
$new_url = add_query_arg('nocache', time(), $permalink);
wp_redirect($new_url);
exit;
exit();
}
if (!is_user_logged_in()) {
return '<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #e0e0e0; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); z-index: 999; text-align: center;">
<p>You must be logged in to handle the attendance control.</p>
</div>';
}
if (!(current_user_can('administrator') || current_user_can('comissao_secretaria') || current_user_can('comissao_suporte')) && !current_user_can('contributor')) {
return '<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #e0e0e0; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); z-index: 999; text-align: center;">
<p>You do not have the required permissions to handle the attendance control.</p>
</div>';
}
global $wpdb;
$success_message = '';
$selected_activity = isset($_POST['selected_activity']) ? intval($_POST['selected_activity']) : (isset($_GET['selected_activity']) ? intval($_GET['selected_activity']) : 0);
$selected_status = isset($_POST['statusFilter']) ? sanitize_text_field($_POST['statusFilter']) : (isset($_GET['statusFilter']) ? sanitize_text_field($_GET['statusFilter']) : 'Approved');
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['qr_scanner_used']) && $_POST['qr_scanner_used'] == '1') {
$hashed_user_id = sanitize_text_field($_POST['qr_code_message']);
$filtered_user_id = verifyUserBasedOnQRCode($hashed_user_id);
if ($selected_activity === -1 || $selected_activity > 0) {
$status_condition = $selected_status === 'Not Requested' ? 'Not Requested' : $selected_status;
$query = $wpdb->prepare("
SELECT e.id as enrollment_id, e.user_id, e.status, u.user_email, um1.meta_value as full_name, a.name as activity_name, a.id as activity_id
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE e.user_id = %d AND e.status = %s
", $filtered_user_id, $status_condition);
if ($selected_activity === -1) {
$query .= " AND a.type = 'Main Event' AND (a.modality = 'In-person' OR a.modality = 'Hybrid')";
} else {
$query .= $wpdb->prepare(" AND e.activity_id = %d", $selected_activity);
}
$enrollments = $wpdb->get_results($query);
if ($enrollments) {
foreach ($enrollments as $enrollment) {
$existing_attendance = $wpdb->get_var($wpdb->prepare("
SELECT attended FROM {$wpdb->prefix}sige_enrollment_attendance_control
WHERE enrollment_id = %d
", $enrollment->enrollment_id));
if ($existing_attendance === 'yes') {
$success_message .= '
<div class="notice notice-warning" style="position: relative; margin-bottom: 10px; background-color: #fff3cd; padding: 20px; border-radius: 10px;">
<button class="notice-close" style="position: absolute; top: 10px; right: 10px; background-color: transparent; border: none; font-size: 20px; cursor: pointer;">&times;</button>
<p>Mr./Mrs. ' . esc_html($enrollment->full_name) . '</p>
<p>Email: ' . esc_html($enrollment->user_email) . '</p>
<p>You have already attended the ' . esc_html($enrollment->activity_name) . '</p>
</div>';
} else {
if ($existing_attendance) {
$wpdb->update(
"{$wpdb->prefix}sige_enrollment_attendance_control",
['attended' => 'yes'],
['enrollment_id' => $enrollment->enrollment_id]
);
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_enrollment_attendance_control",
[
'enrollment_id' => $enrollment->enrollment_id,
'attended' => 'yes'
]
);
}
send_email_notification($enrollment->user_id, 'yes', $enrollment->activity_id);
$enrollment_date = isset($enrollment->enrollment_date) ? esc_html(date('d-m-Y', strtotime($enrollment->enrollment_date))) : 'N/A';
$success_message .= '
<div class="notice notice-success" style="position: relative; margin-bottom: 10px; background-color: #d4edda; padding: 20px; border-radius: 10px;">
<button class="notice-close" style="position: absolute; top: 10px; right: 10px; background-color: transparent; border: none; font-size: 20px; cursor: pointer;">&times;</button>
<p>Mr./Mrs. ' . esc_html($enrollment->full_name) . '</p>
<p>Email: ' . esc_html($enrollment->user_email) . '</p>
<p>Thank you for attending the ' . esc_html($enrollment->activity_name) . '</p>
<p>Date of the Activity: ' . $enrollment_date . '</p>
<p>You will soon receive an email confirming your participation.</p>
</div>';
}
}
} else {
if ($selected_status === 'Not Requested') {
$new_enrollment_data = [
'activity_id' => $selected_activity === -1 ? $wpdb->get_var("SELECT id FROM {$wpdb->prefix}sige_activities WHERE modality = 'Hybrid' AND type = 'Main Event' LIMIT 1") : $selected_activity,
'user_id' => $filtered_user_id,
'enrollment_date' => current_time('mysql'),
'status' => 'Not Requested'
];
$wpdb->insert("{$wpdb->prefix}sige_enrollments", $new_enrollment_data);
$new_enrollment_id = $wpdb->insert_id;
if ($new_enrollment_id) {
$wpdb->insert("{$wpdb->prefix}sige_enrollment_attendance_control", [
'enrollment_id' => $new_enrollment_id,
'attended' => 'yes'
]);
// Fetch new user's email and full name for the email
$new_enrollment_user = $wpdb->get_row($wpdb->prepare("
SELECT u.user_email, um1.meta_value as full_name
FROM {$wpdb->prefix}users u
LEFT JOIN {$wpdb->prefix}usermeta um1 ON u.ID = um1.user_id AND um1.meta_key = 'full_name'
WHERE u.ID = %d
", $filtered_user_id));
// Send email for the new enrollment and attendance
if ($new_enrollment_user) {
$to = $new_enrollment_user->user_email;
$subject = 'Your Enrollment and Attendance Have Been Recorded';
$message = 'Dear ' . esc_html($new_enrollment_user->full_name) . ',<br><br>' .
'You have been successfully enrolled in the activity, and your attendance has been recorded.<br>' .
'Thank you for your participation!<br><br>' .
'Best regards,<br>The Event Team';
$headers = ['Content-Type: text/html; charset=UTF-8'];
// Send the email
wp_mail($to, $subject, $message, $headers);
}
// Log the email variables for debugging
//error_log("New enrollment email sent to: " . esc_html($new_enrollment_user->user_email));
//error_log("New enrollment user full name: " . esc_html($new_enrollment_user->full_name));
$success_message .= '
<div class="notice notice-success" style="position: relative; margin-bottom: 10px; background-color: #d4edda; padding: 20px; border-radius: 10px;">
<button class="notice-close" style="position: absolute; top: 10px; right: 10px; background-color: transparent; border: none; font-size: 20px; cursor: pointer;">&times;</button>
<p>A new enrollment has been added and attendance has been recorded.</p>
</div>';
}
} else {
$success_message .= '
<div class="notice notice-error" style="position: relative; margin-bottom: 10px; background-color: #f8d7da; padding: 20px; border-radius: 10px;">
<button class="notice-close" style="position: absolute; top: 10px; right: 10px; background-color: transparent; border: none; font-size: 20px; cursor: pointer;">&times;</button>
<p>No enrollments found for the user with the selected status.</p>
</div>';
}
}
// Store success message in session and reload the page with the selected_activity and statusFilter in the URL
$_SESSION['success_message'] = $success_message;
wp_safe_redirect(add_query_arg(['selected_activity' => $selected_activity, 'statusFilter' => $selected_status]));
exit;
}
}
}
// Display the success message if it exists
if (isset($_SESSION['success_message'])) {
echo $_SESSION['success_message'];
unset($_SESSION['success_message']); // Clear the message after displaying it
}
// Fetch enrollments with the selected status
$query = "
SELECT e.id as enrollment_id, e.activity_id, a.name as activity_name, e.user_id, um1.meta_value as full_name, u.user_email, e.enrollment_date, e.status, ac.attended
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.status = %s
";
$status_condition = $selected_status === 'Not Requested' ? 'Not Requested' : $selected_status;
$query = $wpdb->prepare($query, $status_condition);
if ($selected_activity === -1) {
$query .= " AND a.type = 'Main Event' AND (a.modality = 'In-person' OR a.modality = 'Hybrid')";
} elseif ($selected_activity > 0) {
$query .= $wpdb->prepare(" AND a.id = %d", $selected_activity);
}
$enrollments = $wpdb->get_results($query);
$activities = $wpdb->get_results("SELECT id, name FROM {$wpdb->prefix}sige_activities WHERE modality IN ('In-person', 'Hybrid') AND YEAR(start_date) = YEAR(CURDATE());")
?>
<div class="wrap">
<h2>Attendance Control</h2>
<div style="background-color: #f0f0f0; padding: 20px; border-radius: 5px; margin-bottom: 20px; text-align: center;">
<div style="margin-bottom: 20px;">
<div id="qr-reader" style="width:300px; margin: 0 auto;"></div>
<button id="start-qr-reader" class="button button-secondary" style="display: inline-block; margin-top: 10px; width: 300px;">Start QR Scanner</button>
</div>
<form method="post" action="" id="attendanceForm" style="display: flex; flex-direction: column; gap: 10px; align-items: center;">
<input type="hidden" name="qr_scanner_used" id="qr_scanner_used" value="0" />
<input type="hidden" name="qr_code_message" id="qr_code_message" />
<div style="display: flex; align-items: center; gap: 10px;">
<label for="activityFilter">Activity:</label>
<select id="activityFilter" name="selected_activity" form="attendanceForm" onchange="this.form.submit();" required>
<option value="">Select an Activity</option>
<option value="-1" <?php selected($selected_activity, -1); ?>>Main Event</option>
<?php foreach ($activities as $activity) { ?>
<option value="<?php echo esc_attr($activity->id); ?>" <?php selected($selected_activity, $activity->id); ?>><?php echo esc_html($activity->name); ?></option>
<?php } ?>
</select>
</div>
<div style="display: flex; align-items: center; gap: 10px;">
<label for="statusFilter">Status:</label>
<select id="statusFilter" name="statusFilter" form="attendanceForm" onchange="this.form.submit();" required>
<option value="Approved" <?php selected($selected_status, 'Approved'); ?>>Approved</option>
<option value="Waiting List" <?php selected($selected_status, 'Waiting List'); ?>>Waiting List</option>
<option value="Not Requested" <?php selected($selected_status, 'Not Requested'); ?>>Not Requested</option>
</select>
</div>
</form>
</div>
<div style="background-color: #f0f0f0; padding: 20px; border-radius: 5px; overflow-x: auto; margin-bottom: 20px;">
<table id="attendanceTable" class="display" style="width:100%">
<thead>
<tr>
<th>Activity Name</th>
<th>User ID</th>
<th>User Full Name</th>
<th>Email</th>
<th>Enrollment Date</th>
<th>Status</th>
<th>Attended</th>
</tr>
</thead>
<tbody id="tableBody">
<?php
if ($enrollments) {
foreach ($enrollments as $enrollment) {
?>
<tr data-attended="<?php echo esc_attr($enrollment->attended); ?>">
<td><?php echo esc_html($enrollment->activity_name); ?></td>
<td><?php echo esc_html($enrollment->user_id); ?></td>
<td><?php echo esc_html($enrollment->full_name); ?></td>
<td><?php echo esc_html($enrollment->user_email); ?></td>
<td><?php echo esc_html($enrollment->enrollment_date); ?></td>
<td><?php echo esc_html($enrollment->status); ?></td>
<td><?php echo esc_html($enrollment->attended); ?></td>
</tr>
<?php
}
} else {
?>
<tr>
<td colspan="7">No enrollments found for the selected status.</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
<div style="background-color: #f0f0f0; padding: 20px; border-radius: 5px; text-align: center;">
<button id="export-csv" class="button button-secondary" style="margin-top: 10px;">Export to CSV</button>
</div>
</div>
<script src="https://cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.24/js/dataTables.jqueryui.min.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.24/css/dataTables.jqueryui.min.css">
<script>
jQuery(document).ready(function($) {
function applyAttendanceStyles() {
$('#attendanceTable tbody tr').each(function() {
const attended = $(this).data('attended');
if (attended === 'yes') {
$(this).css('background-color', '#33ff7a');
} else if (attended === 'no') {
$(this).css('background-color', '#f54949');
} else if (attended === '') {
$(this).css('background-color', '#d1ca3b');
}
});
}
function initializeQrCodeScanner() {
if (typeof Html5Qrcode !== "undefined") {
const qrReader = new Html5Qrcode("qr-reader");
const startQrReaderBtn = document.getElementById("start-qr-reader");
const qrCodeMessageInput = document.getElementById("qr_code_message");
const qrScannerUsedInput = document.getElementById("qr_scanner_used");
let qrScannerRunning = false;
startQrReaderBtn.addEventListener("click", function() {
if (!qrScannerRunning) {
qrReader.start({
facingMode: "environment"
}, {
fps: 10,
qrbox: 250
},
qrCodeMessage => {
qrCodeMessageInput.value = qrCodeMessage;
qrScannerUsedInput.value = 1; // Set this to indicate scanner was used
qrReader.stop().then(() => {
qrScannerRunning = false;
startQrReaderBtn.textContent = "Start QR Scanner";
document.getElementById("attendanceForm").submit();
});
},
errorMessage => {
console.warn(`QR Code scanning error: ${errorMessage}`);
}
).then(() => {
qrScannerRunning = true;
startQrReaderBtn.textContent = "Stop QR Scanner";
}).catch(err => {
console.error(`Unable to start QR Code scanning: ${err}`);
});
} else {
qrReader.stop().then(() => {
qrScannerRunning = false;
startQrReaderBtn.textContent = "Start QR Scanner";
}).catch(err => {
console.error(`Unable to stop QR Code scanning: ${err}`);
});
}
});
} else {
console.error("Html5Qrcode library is not loaded properly.");
}
}
function exportToCsv(filename, rows) {
const processRow = function(row) {
let finalVal = '';
for (let j = 0; j < row.length; j++) {
let innerValue = row[j] === null ? '' : row[j].toString();
if (row[j] instanceof Date) {
innerValue = row[j].toLocaleString();
}
let result = innerValue.replace(/"/g, '""');
if (result.search(/("|,|\n)/g) >= 0)
result = '"' + result + '"';
if (j > 0)
finalVal += ';'; // Changed to semicolon
finalVal += result;
}
return finalVal + '\n';
};
let csvFile = '';
for (let i = 0; i < rows.length; i++) {
csvFile += processRow(rows[i]);
}
const blob = new Blob([csvFile], {
type: 'text/csv;charset=utf-8;'
});
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement("a");
if (link.download !== undefined) { // feature detection
const url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
function generateCsvFileName() {
const now = new Date();
const formattedDate = `${("0" + now.getDate()).slice(-2)}_${("0" + (now.getMonth() + 1)).slice(-2)}_${now.getFullYear()}_${("0" + now.getHours()).slice(-2)}_${("0" + now.getMinutes()).slice(-2)}_${("0" + now.getSeconds()).slice(-2)}`;
return `attendance_${formattedDate}.csv`;
}
document.getElementById('export-csv').addEventListener('click', function() {
const table = document.querySelector('#attendanceTable');
const rows = [];
rows.push(["Activity Name", "User ID", "User Full Name", "Email", "Enrollment Date", "Status", "Attended"]);
table.querySelectorAll('tbody tr').forEach(function(row) {
const rowData = [];
row.querySelectorAll('td').forEach(function(cell, index) {
if (index < 7) {
rowData.push(cell.innerText.trim());
}
});
rows.push(rowData);
});
exportToCsv(generateCsvFileName(), rows);
});
initializeQrCodeScanner();
$('#attendanceTable').DataTable({
paging: true,
searching: true,
lengthChange: true,
pageLength: -1,
autoWidth: false,
scrollX: true,
order: [
[2, 'asc']
],
lengthMenu: [
[10, 25, 50, 100, 200, 500, -1],
[10, 25, 50, 100, 200, 500, "All"]
],
language: {
lengthMenu: "Show _MENU_ entries",
info: "Showing _START_ to _END_ of _TOTAL_ entries",
infoFiltered: "(filtered from _MAX_ total entries)",
paginate: {
previous: "Previous",
next: "Next"
}
},
// Call applyAttendanceStyles after each table redraw
drawCallback: function() {
applyAttendanceStyles();
}
});
// Auto-hide success message after 5 seconds
setTimeout(function() {
$('.notice').fadeOut('slow', function() {
$(this).remove();
$('#start-qr-reader').click();
});
}, 10000);
// Close button logic for notices
$(document).on('click', '.notice-close', function() {
$(this).closest('.notice').fadeOut('slow', function() {
$(this).remove();
$('#start-qr-reader').click();
});
});
});
</script>
<?php
return ob_get_clean();
}
add_shortcode('frontend_attendance_control_automatic', 'frontendAttendanceControlAutomatic');