Restore to commit 74e578279624c6045ca440a3459ebfa1f8d54191

This commit is contained in:
southseact-3d
2026-02-07 20:32:41 +00:00
commit ed67b7741b
252 changed files with 99814 additions and 0 deletions

View File

@@ -0,0 +1,238 @@
<?php
/**
* Admin class for managing announcements in WordPress admin
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
class PC_Announcements_274_Admin {
/**
* Constructor
*/
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
add_action('wp_ajax_pc_announcements_274_action', array($this, 'handle_ajax_requests'));
}
/**
* Add admin menu items
*/
public function add_admin_menu() {
add_menu_page(
__('Announcements', 'pc-announcements-274'),
__('Announcements', 'pc-announcements-274'),
'manage_options',
'pc-announcements-274',
array($this, 'render_announcements_page'),
'dashicons-megaphone',
25
);
add_submenu_page(
'pc-announcements-274',
__('All Announcements', 'pc-announcements-274'),
__('All Announcements', 'pc-announcements-274'),
'manage_options',
'pc-announcements-274',
array($this, 'render_announcements_page')
);
add_submenu_page(
'pc-announcements-274',
__('Add New', 'pc-announcements-274'),
__('Add New', 'pc-announcements-274'),
'manage_options',
'pc-announcements-274-add',
array($this, 'render_add_announcement_page')
);
}
/**
* Enqueue admin scripts and styles
*/
public function enqueue_admin_scripts($hook) {
if (strpos($hook, 'pc-announcements-274') === false) {
return;
}
wp_enqueue_style('pc-announcements-274-admin-style', PC_ANNOUNCEMENTS_274_PLUGIN_URL . 'admin/css/admin-style.css', array('wp-admin'), PC_ANNOUNCEMENTS_274_VERSION);
wp_enqueue_media();
wp_enqueue_script('pc-announcements-274-admin-script', PC_ANNOUNCEMENTS_274_PLUGIN_URL . 'admin/js/admin-script.js', array('jquery'), PC_ANNOUNCEMENTS_274_VERSION, true);
wp_localize_script('pc-announcements-274-admin-script', 'pc_announcements_274_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('pc_announcements_274_nonce'),
'i18n' => array(
'error_occurred' => __('An error occurred. Please try again.', 'pc-announcements-274'),
'choose_image' => __('Choose Image', 'pc-announcements-274'),
'preview' => __('Preview', 'pc-announcements-274'),
'end_date_warning' => __('End date should be after start date.', 'pc-announcements-274')
)
));
}
/**
* Render main announcements page
*/
public function render_announcements_page() {
$current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
$per_page = 20;
$offset = ($current_page - 1) * $per_page;
global $wpdb;
$table_name = PC_Announcements_274_Install::get_table_name();
if (empty($table_name)) {
include PC_ANNOUNCEMENTS_274_PLUGIN_DIR . 'admin/templates/error-page.php';
return;
}
// Get total count
$total = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
if ($total === null) {
$total = 0;
}
$total_pages = ceil($total / $per_page);
// Get announcements
$announcements = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name ORDER BY created_at DESC LIMIT %d OFFSET %d",
$per_page, $offset
));
if ($announcements === null) {
$announcements = array();
}
include PC_ANNOUNCEMENTS_274_PLUGIN_DIR . 'admin/templates/list-page.php';
}
/**
* Render add new announcement page
*/
public function render_add_announcement_page() {
$announcement_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$announcement = null;
if ($announcement_id > 0) {
global $wpdb;
$table_name = PC_Announcements_274_Install::get_table_name();
if (!empty($table_name)) {
$announcement = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $announcement_id));
}
}
include PC_ANNOUNCEMENTS_274_PLUGIN_DIR . 'admin/templates/edit-page.php';
}
/**
* Handle AJAX requests
*/
public function handle_ajax_requests() {
check_ajax_referer('pc_announcements_274_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions.', 'pc-announcements-274'));
}
$action = isset($_POST['sub_action']) ? sanitize_text_field($_POST['sub_action']) : '';
switch ($action) {
case 'save_announcement':
$this->save_announcement();
break;
case 'delete_announcement':
$this->delete_announcement();
break;
default:
wp_send_json_error(array('message' => __('Invalid action.', 'pc-announcements-274')));
}
}
/**
* Save announcement
*/
private function save_announcement() {
global $wpdb;
$table_name = PC_Announcements_274_Install::get_table_name();
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$title = sanitize_text_field($_POST['title']);
$message = wp_kses_post($_POST['message']);
$banner_color = sanitize_hex_color($_POST['banner_color']);
$link_url = esc_url_raw($_POST['link_url']);
$image_url = esc_url_raw($_POST['image_url']);
$start_date = !empty($_POST['start_date']) ? sanitize_text_field($_POST['start_date']) : null;
$end_date = !empty($_POST['end_date']) ? sanitize_text_field($_POST['end_date']) : null;
$status = sanitize_text_field($_POST['status']);
if (empty($title)) {
wp_send_json_error(array('message' => __('Title is required.', 'pc-announcements-274')));
}
if (empty($banner_color)) {
$banner_color = '#0d47a1';
}
$data = array(
'title' => $title,
'message' => $message,
'banner_color' => $banner_color,
'link_url' => $link_url,
'image_url' => $image_url,
'start_date' => $start_date,
'end_date' => $end_date,
'status' => $status,
'updated_at' => current_time('mysql')
);
$format = array('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s');
if ($id > 0) {
$result = $wpdb->update($table_name, $data, array('id' => $id), $format, array('%d'));
} else {
$data['created_at'] = current_time('mysql');
$data['created_by'] = get_current_user_id();
$format = array('%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s');
$result = $wpdb->insert($table_name, $data, $format);
$id = $wpdb->insert_id;
}
if ($result === false) {
wp_send_json_error(array('message' => __('Failed to save announcement.', 'pc-announcements-274')));
}
wp_send_json_success(array(
'message' => $id > 0 && isset($_POST['id']) ? __('Announcement updated successfully!', 'pc-announcements-274') : __('Announcement created successfully!', 'pc-announcements-274'),
'id' => $id
));
}
/**
* Delete announcement
*/
private function delete_announcement() {
global $wpdb;
$table_name = PC_Announcements_274_Install::get_table_name();
$id = intval($_POST['id']);
if ($id <= 0) {
wp_send_json_error(array('message' => __('Invalid announcement ID.', 'pc-announcements-274')));
}
$result = $wpdb->delete($table_name, array('id' => $id), array('%d'));
if ($result === false) {
wp_send_json_error(array('message' => __('Failed to delete announcement.', 'pc-announcements-274')));
}
wp_send_json_success(array('message' => __('Announcement deleted successfully!', 'pc-announcements-274')));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,199 @@
jQuery(document).ready(function($) {
'use strict';
// Form submission
$('#pc-announcements-274-form').on('submit', function(e) {
e.preventDefault();
var $form = $(this);
var $submitBtn = $form.find('button[type="submit"]');
var originalText = $submitBtn.text();
// Show loading state
$submitBtn.prop('disabled', true).text('Saving...');
$.ajax({
url: pc_announcements_274_ajax.ajax_url,
type: 'POST',
data: $form.serialize(),
dataType: 'json',
success: function(response) {
if (response.success) {
// Show success message
$('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p></div>')
.insertAfter('.wp-header-end')
.delay(3000)
.fadeOut(function() {
$(this).remove();
});
// Redirect to list page
setTimeout(function() {
window.location.href = 'admin.php?page=pc-announcements-274&message=success';
}, 1000);
} else {
// Show error message
$('<div class="notice notice-error is-dismissible"><p>' + response.data.message + '</p></div>')
.insertAfter('.wp-header-end');
}
},
error: function() {
$('<div class="notice notice-error is-dismissible"><p>' + pc_announcements_274_ajax.i18n.error_occurred + '</p></div>')
.insertAfter('.wp-header-end');
},
complete: function() {
// Restore button state
$submitBtn.prop('disabled', false).text(originalText);
}
});
});
// Delete confirmation
$('.pc-announcements-274-delete-btn').on('click', function(e) {
e.preventDefault();
var announcementId = $(this).data('id');
var $modal = $('#pc-announcements-274-delete-modal');
// Show modal
$modal.show();
// Handle delete confirmation
$modal.find('.pc-announcements-274-confirm-delete').off('click').on('click', function() {
$.ajax({
url: pc_announcements_274_ajax.ajax_url,
type: 'POST',
data: {
action: 'pc_announcements_274_action',
sub_action: 'delete_announcement',
id: announcementId,
nonce: pc_announcements_274_ajax.nonce
},
dataType: 'json',
success: function(response) {
if (response.success) {
// Remove the row from table
$('button[data-id="' + announcementId + '"]').closest('tr').fadeOut(function() {
$(this).remove();
// Show empty state if no items left
if ($('.pc-announcements-274-wrap .wp-list-table tbody tr').length === 0) {
location.reload();
}
});
// Show success message
$('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p></div>')
.insertAfter('.wp-header-end')
.delay(3000)
.fadeOut(function() {
$(this).remove();
});
} else {
// Show error message
$('<div class="notice notice-error is-dismissible"><p>' + response.data.message + '</p></div>')
.insertAfter('.wp-header-end');
}
},
error: function() {
$('<div class="notice notice-error is-dismissible"><p>' + pc_announcements_274_ajax.i18n.error_occurred + '</p></div>')
.insertAfter('.wp-header-end');
},
complete: function() {
// Hide modal
$modal.hide();
}
});
});
});
// Close modal handlers
$('#pc-announcements-274-delete-modal').on('click', '.pc-announcements-274-cancel-delete, .pc-announcements-274-modal-backdrop', function() {
$('#pc-announcements-274-delete-modal').hide();
});
// Close modal with Escape key
$(document).on('keydown', function(e) {
if (e.keyCode === 27) { // Escape key
$('#pc-announcements-274-delete-modal').hide();
}
});
// Media upload functionality
var customUploader;
$('.pc-announcements-274-upload-image-btn').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var $inputField = $button.siblings('input[type="url"]');
// If the uploader object has already been created, reopen the dialog
if (customUploader) {
customUploader.open();
return;
}
// Extend the wp.media object
customUploader = wp.media.frames.file_frame = wp.media({
title: pc_announcements_274_ajax.i18n.choose_image,
button: {
text: pc_announcements_274_ajax.i18n.choose_image
},
multiple: false
});
// When a file is selected, grab the URL and set it as the text field's value
customUploader.on('select', function() {
var attachment = customUploader.state().get('selection').first().toJSON();
$inputField.val(attachment.url);
// Update preview if exists
var $preview = $inputField.siblings('.pc-announcements-274-image-preview');
if ($preview.length === 0) {
$preview = $('<div class="pc-announcements-274-image-preview"></div>').insertAfter($inputField.parent());
}
$preview.html('<img src="' + attachment.url + '" alt="' + pc_announcements_274_ajax.i18n.preview + '" style="max-width: 200px; height: auto;">');
});
// Open the uploader dialog
customUploader.open();
});
// Auto-hide notices
$('.notice.is-dismissible').on('click', '.notice-dismiss', function() {
$(this).closest('.notice').fadeOut(function() {
$(this).remove();
});
});
// Image URL field change handler
$('input[name="image_url"]').on('input', function() {
var url = $(this).val();
var $preview = $(this).siblings('.pc-announcements-274-image-preview');
if (url) {
if ($preview.length === 0) {
$preview = $('<div class="pc-announcements-274-image-preview"></div>').insertAfter($(this).parent());
}
$preview.html('<img src="' + url + '" alt="' + pc_announcements_274_ajax.i18n.preview + '" style="max-width: 200px; height: auto;" onerror="this.style.display=\'none\'">');
} else if ($preview.length > 0) {
$preview.empty();
}
});
// Date/time validation
$('#start_date, #end_date').on('change', function() {
var startDate = $('#start_date').val();
var endDate = $('#end_date').val();
if (startDate && endDate && new Date(startDate) >= new Date(endDate)) {
$('<div class="notice notice-warning is-dismissible"><p>' + pc_announcements_274_ajax.i18n.end_date_warning + '</p></div>')
.insertAfter('.wp-header-end')
.delay(5000)
.fadeOut(function() {
$(this).remove();
});
}
});
});

View File

@@ -0,0 +1,197 @@
<?php
/**
* Edit/Add announcement page template
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
$is_edit = !empty($announcement) && isset($announcement->id) && $announcement->id > 0;
$page_title = $is_edit ? __('Edit Announcement', 'pc-announcements-274') : __('Add New Announcement', 'pc-announcements-274');
?>
<div class="wrap pc-announcements-274-wrap">
<h1 class="wp-heading-inline">
<?php echo esc_html($page_title); ?>
</h1>
<a href="<?php echo admin_url('admin.php?page=pc-announcements-274'); ?>" class="page-title-action">
<?php _e('Back to List', 'pc-announcements-274'); ?>
</a>
<hr class="wp-header-end">
<form id="pc-announcements-274-form" class="pc-announcements-274-form">
<div class="pc-announcements-274-main-content">
<div class="pc-announcements-274-card">
<div class="pc-announcements-274-card-header">
<h2><?php _e('Announcement Details', 'pc-announcements-274'); ?></h2>
</div>
<div class="pc-announcements-274-card-body">
<div class="pc-announcements-274-form-row">
<div class="pc-announcements-274-form-group">
<label for="title" class="pc-announcements-274-label">
<?php _e('Title', 'pc-announcements-274'); ?> <span class="required">*</span>
</label>
<input type="text" id="title" name="title" class="regular-text" required
value="<?php echo $is_edit ? esc_attr($announcement->title) : ''; ?>"
placeholder="<?php _e('Enter announcement title', 'pc-announcements-274'); ?>">
</div>
</div>
<div class="pc-announcements-274-form-row">
<div class="pc-announcements-274-form-group">
<label for="banner_color" class="pc-announcements-274-label">
<?php _e('Banner Color', 'pc-announcements-274'); ?>
</label>
<div class="pc-announcements-274-color-picker">
<input type="color" id="banner_color" name="banner_color"
value="<?php echo $is_edit ? esc_attr($announcement->banner_color) : '#0d47a1'; ?>"
style="width: 60px; height: 40px; padding: 2px; cursor: pointer;">
<input type="text" id="banner_color_text" class="regular-text"
value="<?php echo $is_edit ? esc_attr($announcement->banner_color) : '#0d47a1'; ?>"
placeholder="#0d47a1">
</div>
<p class="description">
<?php _e('Choose the background color for the announcement banner', 'pc-announcements-274'); ?>
</p>
</div>
</div>
<div class="pc-announcements-274-form-row">
<div class="pc-announcements-274-form-group">
<label for="link_url" class="pc-announcements-274-label">
<?php _e('Link URL', 'pc-announcements-274'); ?>
</label>
<input type="url" id="link_url" name="link_url" class="regular-text"
value="<?php echo $is_edit ? esc_url($announcement->link_url) : ''; ?>"
placeholder="<?php _e('https://example.com', 'pc-announcements-274'); ?>">
<p class="description">
<?php _e('Enter a URL to make the announcement banner clickable', 'pc-announcements-274'); ?>
</p>
</div>
</div>
<div class="pc-announcements-274-form-row">
<div class="pc-announcements-274-form-group">
<label for="image_url" class="pc-announcements-274-label">
<?php _e('Image URL', 'pc-announcements-274'); ?>
</label>
<div class="pc-announcements-274-media-upload">
<input type="url" id="image_url" name="image_url" class="regular-text"
value="<?php echo $is_edit ? esc_url($announcement->image_url) : ''; ?>"
placeholder="<?php _e('https://example.com/image.jpg', 'pc-announcements-274'); ?>">
<button type="button" class="button pc-announcements-274-upload-image-btn">
<?php _e('Upload Image', 'pc-announcements-274'); ?>
</button>
</div>
<?php if ($is_edit && $announcement->image_url): ?>
<div class="pc-announcements-274-image-preview">
<img src="<?php echo esc_url($announcement->image_url); ?>" alt="<?php _e('Preview', 'pc-announcements-274'); ?>" style="max-width: 200px; height: auto;">
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div class="pc-announcements-274-card">
<div class="pc-announcements-274-card-header">
<h2><?php _e('Scheduling', 'pc-announcements-274'); ?></h2>
</div>
<div class="pc-announcements-274-card-body">
<div class="pc-announcements-274-form-row">
<div class="pc-announcements-274-form-group">
<label for="status" class="pc-announcements-274-label">
<?php _e('Status', 'pc-announcements-274'); ?>
</label>
<select id="status" name="status" class="regular-text">
<option value="active" <?php echo ($is_edit && $announcement->status === 'active') ? 'selected' : ''; ?>>
<?php _e('Active', 'pc-announcements-274'); ?>
</option>
<option value="inactive" <?php echo ($is_edit && $announcement->status === 'inactive') ? 'selected' : ''; ?>>
<?php _e('Inactive', 'pc-announcements-274'); ?>
</option>
<option value="scheduled" <?php echo ($is_edit && $announcement->status === 'scheduled') ? 'selected' : ''; ?>>
<?php _e('Scheduled', 'pc-announcements-274'); ?>
</option>
</select>
</div>
</div>
<div class="pc-announcements-274-form-row">
<div class="pc-announcements-274-form-group">
<label for="start_date" class="pc-announcements-274-label">
<?php _e('Start Date', 'pc-announcements-274'); ?>
</label>
<input type="datetime-local" id="start_date" name="start_date"
value="<?php echo $is_edit && $announcement->start_date ? date('Y-m-d\TH:i', strtotime($announcement->start_date)) : ''; ?>">
<p class="description">
<?php _e('Leave empty to start immediately', 'pc-announcements-274'); ?>
</p>
</div>
<div class="pc-announcements-274-form-group">
<label for="end_date" class="pc-announcements-274-label">
<?php _e('End Date', 'pc-announcements-274'); ?>
</label>
<input type="datetime-local" id="end_date" name="end_date"
value="<?php echo $is_edit && $announcement->end_date ? date('Y-m-d\TH:i', strtotime($announcement->end_date)) : ''; ?>">
<p class="description">
<?php _e('Leave empty to show indefinitely', 'pc-announcements-274'); ?>
</p>
</div>
</div>
</div>
</div>
</div>
<div class="pc-announcements-274-sidebar">
<div class="pc-announcements-274-card">
<div class="pc-announcements-274-card-header">
<h2><?php _e('Publish', 'pc-announcements-274'); ?></h2>
</div>
<div class="pc-announcements-274-card-body">
<input type="hidden" name="id" value="<?php echo $is_edit ? $announcement->id : 0; ?>">
<input type="hidden" name="action" value="pc_announcements_274_action">
<input type="hidden" name="sub_action" value="save_announcement">
<?php wp_nonce_field('pc_announcements_274_nonce', 'nonce'); ?>
<div class="pc-announcements-274-publish-actions">
<button type="submit" class="button button-primary button-large">
<?php echo $is_edit ? __('Update Announcement', 'pc-announcements-274') : __('Create Announcement', 'pc-announcements-274'); ?>
</button>
<a href="<?php echo admin_url('admin.php?page=pc-announcements-274'); ?>" class="button">
<?php _e('Cancel', 'pc-announcements-274'); ?>
</a>
</div>
<?php if ($is_edit): ?>
<div class="pc-announcements-274-form-info">
<p><strong><?php _e('Created:', 'pc-announcements-274'); ?></strong> <?php echo date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($announcement->created_at)); ?></p>
<?php if ($announcement->updated_at !== $announcement->created_at): ?>
<p><strong><?php _e('Last Updated:', 'pc-announcements-274'); ?></strong> <?php echo date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($announcement->updated_at)); ?></p>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
</form>
</div>
<div id="pc-announcements-274-delete-modal" class="pc-announcements-274-modal" style="display: none;">
<div class="pc-announcements-274-modal-backdrop"></div>
<div class="pc-announcements-274-modal-content">
<div class="pc-announcements-274-modal-header">
<h3><?php _e('Delete Announcement', 'pc-announcements-274'); ?></h3>
</div>
<div class="pc-announcements-274-modal-body">
<p><?php _e('Are you sure you want to delete this announcement? This action cannot be undone.', 'pc-announcements-274'); ?></p>
</div>
<div class="pc-announcements-274-modal-footer">
<button type="button" class="button pc-announcements-274-cancel-delete"><?php _e('Cancel', 'pc-announcements-274'); ?></button>
<button type="button" class="button button-danger pc-announcements-274-confirm-delete"><?php _e('Delete', 'pc-announcements-274'); ?></button>
</div>
</div>
</div>

View File

@@ -0,0 +1,30 @@
<?php
/**
* Error page template for database table issues
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
?>
<div class="wrap pc-announcements-274-wrap">
<h1 class="wp-heading-inline">
<?php _e('Announcements', 'pc-announcements-274'); ?>
</h1>
<hr class="wp-header-end">
<div class="pc-announcements-274-card">
<div class="pc-announcements-274-card-header">
<h2><?php _e('Database Error', 'pc-announcements-274'); ?></h2>
</div>
<div class="pc-announcements-274-card-body">
<div class="pc-announcements-274-empty-state">
<div class="pc-announcements-274-empty-icon">⚠️</div>
<h3><?php _e('Database table not found', 'pc-announcements-274'); ?></h3>
<p><?php _e('The announcements database table has not been created yet. Please try deactivating and reactivating the plugin.', 'pc-announcements-274'); ?></p>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,133 @@
<?php
/**
* List page template for announcements
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
?>
<div class="wrap pc-announcements-274-wrap">
<h1 class="wp-heading-inline">
<?php _e('Announcements', 'pc-announcements-274'); ?>
</h1>
<a href="<?php echo admin_url('admin.php?page=pc-announcements-274-add'); ?>" class="page-title-action">
<?php _e('Add New', 'pc-announcements-274'); ?>
</a>
<hr class="wp-header-end">
<?php if (isset($_GET['message']) && $_GET['message'] === 'success'): ?>
<div class="notice notice-success is-dismissible">
<p><?php _e('Announcement saved successfully!', 'pc-announcements-274'); ?></p>
</div>
<?php endif; ?>
<div class="pc-announcements-274-card">
<div class="pc-announcements-274-card-header">
<h2><?php _e('All Announcements', 'pc-announcements-274'); ?></h2>
</div>
<div class="pc-announcements-274-card-body">
<?php if (!empty($announcements) && is_array($announcements)): ?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th scope="col" class="manage-column column-title"><?php _e('Title', 'pc-announcements-274'); ?></th>
<th scope="col" class="manage-column column-status"><?php _e('Status', 'pc-announcements-274'); ?></th>
<th scope="col" class="manage-column column-date"><?php _e('Schedule', 'pc-announcements-274'); ?></th>
<th scope="col" class="manage-column column-date"><?php _e('Created', 'pc-announcements-274'); ?></th>
<th scope="col" class="manage-column column-actions"><?php _e('Actions', 'pc-announcements-274'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($announcements as $announcement): ?>
<?php
$current_time = current_time('timestamp');
$start_timestamp = $announcement->start_date ? strtotime($announcement->start_date) : 0;
$end_timestamp = $announcement->end_date ? strtotime($announcement->end_date) : 9999999999;
$is_active = $announcement->status === 'active' &&
(!$start_timestamp || $current_time >= $start_timestamp) &&
(!$end_timestamp || $current_time <= $end_timestamp);
?>
<tr>
<td class="column-title">
<strong>
<a href="<?php echo admin_url('admin.php?page=pc-announcements-274-add&id=' . $announcement->id); ?>">
<?php echo esc_html($announcement->title); ?>
</a>
</strong>
<?php if ($is_active): ?>
<span class="pc-announcements-274-active-badge"><?php _e('Active', 'pc-announcements-274'); ?></span>
<?php endif; ?>
</td>
<td class="column-status">
<span class="pc-announcements-274-status pc-announcements-274-status-<?php echo esc_attr($announcement->status); ?>">
<?php
$status_labels = array(
'active' => __('Active', 'pc-announcements-274'),
'inactive' => __('Inactive', 'pc-announcements-274'),
'scheduled' => __('Scheduled', 'pc-announcements-274')
);
echo esc_html($status_labels[$announcement->status] ?? $announcement->status);
?>
</span>
</td>
<td class="column-date">
<?php if ($announcement->start_date): ?>
<?php _e('From', 'pc-announcements-274'); ?> <?php echo date_i18n(get_option('date_format'), strtotime($announcement->start_date)); ?><br>
<?php endif; ?>
<?php if ($announcement->end_date): ?>
<?php _e('Until', 'pc-announcements-274'); ?> <?php echo date_i18n(get_option('date_format'), strtotime($announcement->end_date)); ?>
<?php endif; ?>
<?php if (!$announcement->start_date && !$announcement->end_date): ?>
<?php _e('Always', 'pc-announcements-274'); ?>
<?php endif; ?>
</td>
<td class="column-date">
<?php echo date_i18n(get_option('date_format'), strtotime($announcement->created_at)); ?>
</td>
<td class="column-actions">
<a href="<?php echo admin_url('admin.php?page=pc-announcements-274-add&id=' . $announcement->id); ?>" class="button">
<?php _e('Edit', 'pc-announcements-274'); ?>
</a>
<button class="button button-danger pc-announcements-274-delete-btn" data-id="<?php echo $announcement->id; ?>">
<?php _e('Delete', 'pc-announcements-274'); ?>
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php if (!empty($total_pages) && $total_pages > 1): ?>
<div class="tablenav bottom">
<div class="tablenav-pages">
<?php
$current_url = admin_url('admin.php?page=pc-announcements-274');
echo paginate_links(array(
'base' => add_query_arg('paged', '%#%', $current_url),
'format' => '',
'prev_text' => __('&laquo; Previous', 'pc-announcements-274'),
'next_text' => __('Next &raquo;', 'pc-announcements-274'),
'total' => $total_pages,
'current' => $current_page,
));
?>
</div>
</div>
<?php endif; ?>
<?php else: ?>
<div class="pc-announcements-274-empty-state">
<div class="pc-announcements-274-empty-icon">📢</div>
<h3><?php _e('No announcements found', 'pc-announcements-274'); ?></h3>
<p><?php _e('Create your first announcement to get started.', 'pc-announcements-274'); ?></p>
<a href="<?php echo admin_url('admin.php?page=pc-announcements-274-add'); ?>" class="button button-primary">
<?php _e('Add New Announcement', 'pc-announcements-274'); ?>
</a>
</div>
<?php endif; ?>
</div>
</div>
</div>