Remove backup and temp files from tracking
This commit is contained in:
@@ -1,370 +0,0 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
class KTC_Admin {
|
||||
|
||||
public static function enqueue_scripts() {
|
||||
|
||||
// Only load on the Clock page/Front page to keep the rest of WP light
|
||||
//if ( ! is_front_page() && ! is_page('clock') ) { return; }
|
||||
|
||||
wp_enqueue_script(
|
||||
'ktc-app-js',
|
||||
plugins_url( 'assets/ktc-app.js', dirname( __FILE__ ) ),
|
||||
array(),
|
||||
'1.1.0',
|
||||
true //load in footer
|
||||
);
|
||||
|
||||
// Pass PHP data to JS (like our Sovereign Timezone or current shift state)
|
||||
wp_localize_script( 'ktc-app-js', 'ktcData', array(
|
||||
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
||||
'lockoutTime' => 60 // Seconds for the button cooldown
|
||||
));
|
||||
|
||||
$tz_string = get_option( 'ktc_timezone', 'America/Chicago' );
|
||||
wp_add_inline_script( 'ktc-app-js', "const ktcSovereignTZ = '{$tz_string}';", 'before' );
|
||||
|
||||
}
|
||||
|
||||
public static function init() {
|
||||
add_shortcode( 'krista_timeclock', array( __CLASS__, 'render_timeclock' ) );
|
||||
add_shortcode( 'ktc_portal_welcome', array( __CLASS__, 'render_welcome' ) );
|
||||
add_action( 'wp_footer', array( __CLASS__, 'inject_ui_scripts' ) );
|
||||
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
|
||||
add_action( 'admin_menu', array( __CLASS__, 'register_settings_page' ) );
|
||||
|
||||
add_action( 'admin_init', function() {
|
||||
if ( ! current_user_can('manage_options') && ! defined('DOING_AJAX') && $GLOBALS['pagenow'] !== 'profile.php' && current_user_can('ktc_user') ) {
|
||||
wp_safe_redirect( home_url('/') ); exit;
|
||||
}
|
||||
});
|
||||
|
||||
add_action( 'admin_init', function() {
|
||||
add_settings_section( 'ktc_main_section', 'General Configuration', null, 'ktc-settings' );
|
||||
add_settings_field( 'ktc_week_start_field', 'Week Starts On', function() {
|
||||
$val = get_option('ktc_week_start', 'Monday');
|
||||
echo "<select name='ktc_week_start'>
|
||||
<option value='Monday' ".selected($val, 'Monday', false).">Monday</option>
|
||||
<option value='Sunday' ".selected($val, 'Sunday', false).">Sunday</option>
|
||||
</select>";
|
||||
}, 'ktc-settings', 'ktc_main_section' );
|
||||
add_settings_field( 'ktc_timezone_field', 'Sovereign Timezone', array( __CLASS__, 'render_timezone_field' ), 'ktc-settings', 'ktc_main_section' );
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a unified dashboard header.
|
||||
* Consolidates Admin 'Pulse' and User 'Stats' based on capability.
|
||||
*/
|
||||
public static function render_welcome() {
|
||||
if ( ! is_user_logged_in() ) return 'Please log in to continue';
|
||||
|
||||
$user = wp_get_current_user();
|
||||
$is_admin = current_user_can('manage_options');
|
||||
|
||||
// Everyone gets Personal Stats
|
||||
$stats = KTC_Logic::get_user_stats( $user->ID );
|
||||
$user_stat_data = [
|
||||
['label' => 'This Week', 'val' => $stats['week'] . ' hrs', 'color' => '#2196F3'],
|
||||
['label' => 'This Month', 'val' => $stats['month'] . ' hrs', 'color' => '#4CAF50'],
|
||||
['label' => 'My Pending TORs', 'val' => $stats['pending_tor'], 'color' => '#FF9800']
|
||||
];
|
||||
|
||||
ob_start(); ?>
|
||||
|
||||
<!-- PRIMARY CONTAINER: User Personal Stats -->
|
||||
<div class="ktc-welcome-container" style="background: #fff; border: 1px solid #e5e5e5; border-radius: 8px; padding: 25px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); font-family: sans-serif;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 20px;">
|
||||
<div>
|
||||
<h2 style="margin:0; color: #333;">Welcome, <?php echo esc_html( $user->display_name ); ?></h2>
|
||||
<p style="color: #666; margin: 5px 0 0 0; font-size: 13px;">Personal Time Tracking Overview</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap:15px;">
|
||||
<?php foreach ( $user_stat_data as $stat ) : ?>
|
||||
<div style="background:#f9f9f9; padding:15px; border-radius:8px; border-left: 4px solid <?php echo $stat['color']; ?>;">
|
||||
<small style="color:#666; text-transform:uppercase; font-size:10px; font-weight:bold;"><?php echo $stat['label']; ?></small><br>
|
||||
<span style="font-size:20px; font-weight:bold; color:#222;"><?php echo $stat['val']; ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SECONDARY CONTAINER: Admin System Pulse -->
|
||||
<?php if ( $is_admin ) :
|
||||
$pulse = KTC_Logic::get_admin_pulse();
|
||||
$admin_stat_data = [
|
||||
['label' => 'Active Now', 'val' => $pulse['active_now'], 'color' => '#4CAF50'],
|
||||
['label' => 'Pending Edits', 'val' => $pulse['pending_edits'], 'color' => '#2196F3'],
|
||||
['label' => 'System TORs', 'val' => $pulse['total_pending_tor'], 'color' => '#FF9800']
|
||||
];
|
||||
?>
|
||||
<div class="ktc-admin-pulse-container" style="background: #2c3338; border-radius: 8px; padding: 20px; margin-bottom: 30px; color: #eee; font-family: sans-serif;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
||||
<h3 style="margin:0; font-size: 14px; text-transform: uppercase; letter-spacing: 1px;">System Pulse</h3>
|
||||
<span style="background: #edb120; color: #000; font-size: 9px; padding: 2px 8px; border-radius: 4px; font-weight: bold;">ADMIN CONSOLE</span>
|
||||
</div>
|
||||
|
||||
<div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap:15px;">
|
||||
<?php foreach ( $admin_stat_data as $stat ) : ?>
|
||||
<div style="background:rgba(255,255,255,0.05); padding:12px; border-radius:6px; border-top: 2px solid <?php echo $stat['color']; ?>;">
|
||||
<small style="color:#aaa; text-transform:uppercase; font-size:9px; font-weight:bold;"><?php echo $stat['label']; ?></small><br>
|
||||
<span style="font-size:18px; font-weight:bold; color:#fff;"><?php echo $stat['val']; ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 15px; display: flex; gap: 10px;">
|
||||
<a href="<?php echo admin_url('admin.php?page=ktc-settings'); ?>" style="text-decoration:none; color:#bbb; font-size:11px; background: rgba(255,255,255,0.1); padding: 5px 10px; border-radius: 4px;">🛠️ System Settings</a>
|
||||
<a href="<?php echo admin_url('profile.php'); ?>" style="text-decoration:none; color:#bbb; font-size:11px; background: rgba(255,255,255,0.1); padding: 5px 10px; border-radius: 4px;">⚙️ Global Profile</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Action Bar (Logout, etc) -->
|
||||
<div style="display:flex; gap:10px; margin-bottom: 30px;">
|
||||
<a href="<?php echo wp_logout_url( home_url() ); ?>" style="text-decoration:none; color:#d32f2f; font-size:13px; border:1px solid #d32f2f; padding:8px 15px; border-radius:4px;">🚪 Logout</a>
|
||||
</div>
|
||||
|
||||
<!-- Real time clock source -->
|
||||
<div id="ktc-clock-teleport-source" style="display:none;">
|
||||
<div class="ktc-digital-clock" id="ktc-digital-clock">00:00:00</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
private static function stat_box($label, $val, $color) {
|
||||
return "<div style='background:#f9f9f9; padding:15px; border-radius:8px; border-left: 4px solid $color;'>
|
||||
<small style='color:#666; text-transform:uppercase; font-size:10px; font-weight:bold;'>$label</small><br>
|
||||
<span style='font-size:20px; font-weight:bold; color:#222;'>$val</span></div>";
|
||||
}
|
||||
|
||||
public static function render_timeclock() {
|
||||
if ( ! is_user_logged_in() ) return '<p>Please log in.</p>';
|
||||
global $wpdb;
|
||||
$user_id = get_current_user_id();
|
||||
$table_name = $wpdb->prefix . 'ktc_logs';
|
||||
|
||||
$status = $wpdb->get_var( $wpdb->prepare( "SELECT action_type FROM $table_name WHERE user_id = %d ORDER BY timestamp DESC LIMIT 1", $user_id ) ) ?: 'clock_out';
|
||||
$btn_color = ($status === 'clock_in') ? '#d9534f' : '#5cb85c';
|
||||
$next_action = ($status === 'clock_in') ? 'clock_out' : 'clock_in';
|
||||
|
||||
ob_start(); ?>
|
||||
<div style="background: #f4f4f4; padding: 15px; border-radius: 5px; margin-bottom: 20px; display: flex; justify-content: space-between;">
|
||||
<?php if ( $status === 'clock_in' ): $elapsed = KTC_Logic::get_elapsed_time($user_id); ?>
|
||||
<div><strong>Current Shift:</strong> <span id="ktc-live-elapsed" data-seconds="<?php echo $elapsed; ?>"><?php echo KTC_Logic::format_seconds($elapsed); ?></span></div>
|
||||
<?php else: ?>
|
||||
<div><strong>Status:</strong> <span style="color:#666;">Off the Clock</span></div>
|
||||
<?php endif; ?>
|
||||
<div><strong>Weekly Total:</strong> <?php echo KTC_Logic::get_weekly_total($user_id); ?> hrs</div>
|
||||
</div>
|
||||
|
||||
<form method="post" id="ktc-punch-form">
|
||||
<?php wp_nonce_field( 'ktc_punch_action', 'ktc_nonce' ); ?>
|
||||
<input type="hidden" name="ktc_action" value="punch">
|
||||
<button type="submit" id="ktc-punch-button" style="background-color:<?php echo $btn_color; ?>; color:white; padding: 15px 30px; border:none; border-radius:5px; cursor:pointer; font-size: 18px;">
|
||||
<?php echo ucfirst(str_replace('_',' ',$next_action)); ?>
|
||||
</button>
|
||||
<div id="ktc-timer" style="margin:5px 0 10px 5px; font-size:12px; color:#999; display:none;">Processing... <span id="ktc-countdown">60</span>s</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
$history = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_name WHERE user_id = %d ORDER BY timestamp DESC LIMIT 10", $user_id ) );
|
||||
if ( $history ): ?>
|
||||
<h3>Recent Activity</h3>
|
||||
<table style="width:100%; border-collapse: collapse; margin-top: 20px;">
|
||||
<?php foreach ( $history as $log ):
|
||||
$ts_local = KTC_Logic::get_local_timestamp($log->timestamp);
|
||||
$orig_time = wp_date( 'D, M j, g:i a', $ts_local );
|
||||
$is_today = (wp_date('Y-m-d', $ts_local) === (new DateTime('now', new DateTimeZone(KTC_TIMEZONE)))->format('Y-m-d')) ? 'true' : 'false';
|
||||
?>
|
||||
<tr style="border-bottom: 1px solid #eee;">
|
||||
<td style="padding: 10px 0;"><?php echo $orig_time; ?></td>
|
||||
<td><?php echo ucfirst(str_replace('_',' ',$log->action_type)); ?></td>
|
||||
<td style="text-align:right;"><button type="button" onclick='ktc_open_edit_modal(<?php echo $log->id; ?>, "<?php echo $orig_time; ?>", <?php echo $is_today; ?>)' style="...">Edit</button></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( current_user_can('manage_options') ) echo self::render_admin_queue(); ?>
|
||||
<?php return ob_get_clean();
|
||||
}
|
||||
|
||||
private static function render_admin_queue() {
|
||||
global $wpdb;
|
||||
$pending = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}ktc_logs WHERE status = 'pending_correction' ORDER BY timestamp DESC");
|
||||
if ( ! $pending ) return '';
|
||||
ob_start(); ?>
|
||||
<div style="margin-top:40px; border:2px solid #0073aa; padding:20px; border-radius:8px;">
|
||||
<h3>Admin: Correction Queue</h3>
|
||||
<?php foreach($pending as $req): $u = get_userdata($req->user_id); ?>
|
||||
<div style="display:flex; justify-content:space-between; padding:10px 0; border-bottom:1px solid #eee;">
|
||||
<span><strong><?php echo $u->display_name; ?></strong>: <?php echo wp_date('g:i a', KTC_Logic::get_local_timestamp($req->proposed_timestamp)); ?></span>
|
||||
<div>
|
||||
<a href="?ktc_admin_action=approve&log_id=<?php echo $req->id; ?>" style="background:#5cb85c; color:#fff; padding:5px; text-decoration:none;">Approve</a>
|
||||
<a href="?ktc_admin_action=reject&log_id=<?php echo $req->id; ?>" style="background:#d9534f; color:#fff; padding:5px; text-decoration:none;">Reject</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php return ob_get_clean();
|
||||
}
|
||||
|
||||
/* public static function inject_ui_scripts() {
|
||||
if ( ! is_front_page() && ! is_page('clock') ) return; ?>
|
||||
<div id="ktc_edit_modal" style="display:none; position:fixed; z-index:9999; left:0; top:0; width:100%; height:100%; background:rgba(0,0,0,0.6);">
|
||||
<div style="background:#fff; margin:10% auto; padding:25px; border-radius:8px; width:320px;">
|
||||
<h3>Request Correction</h3>
|
||||
<form method="post">
|
||||
<input type="hidden" name="ktc_edit_id" id="ktc_edit_id">
|
||||
<input type="time" name="ktc_proposed_time" required style="width:100%;">
|
||||
<textarea name="ktc_edit_notes" style="width:100%; margin-top:10px;"></textarea>
|
||||
<button type="submit" style="background:#5cb85c; color:#fff; border:none; padding:10px 20px; margin-top:10px;">Submit</button>
|
||||
<button type="button" onclick="document.getElementById('ktc_edit_modal').style.display='none'">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php }
|
||||
*/
|
||||
public static function inject_ui_scripts() {
|
||||
if ( ! is_front_page() && ! is_page('clock') ) return; ?>
|
||||
|
||||
<div id="ktc_edit_modal" style="display:none; position:fixed; z-index:9999; left:0; top:0; width:100%; height:100%; background:rgba(0,0,0,0.6);">
|
||||
<div style="background:#fff; margin:10% auto; padding:25px; border-radius:8px; width:320px;">
|
||||
<h3>Request Correction</h3>
|
||||
|
||||
<!-- THE MISSING LINK: Add this line -->
|
||||
<p id="ktc_modal_orig_time" style="color: #666; font-size: 0.9em; margin-bottom: 15px;"></p>
|
||||
|
||||
<form method="post">
|
||||
<?php wp_nonce_field( 'ktc_punch_action', 'ktc_nonce' ); ?>
|
||||
<input type="hidden" name="ktc_action" value="edit_request">
|
||||
<input type="hidden" name="ktc_edit_id" id="ktc_edit_id">
|
||||
|
||||
<label>Proposed Time:</label>
|
||||
<input type="time" name="ktc_proposed_time" id="ktc_proposed_time" required style="width:100%;">
|
||||
|
||||
<label style="display:block; margin-top:10px;">Reason/Notes:</label>
|
||||
<textarea name="ktc_edit_notes" style="width:100%;"></textarea>
|
||||
|
||||
<button type="submit" style="background:#5cb85c; color:#fff; border:none; padding:10px 20px; margin-top:15px; cursor:pointer;">Submit</button>
|
||||
<button type="button" onclick="document.getElementById('ktc_edit_modal').style.display='none'" style="background:#ccc; border:none; padding:10px 20px; margin-top:15px; cursor:pointer;">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php }
|
||||
|
||||
public static function register_settings_page() {
|
||||
// 1. Main Menu Page
|
||||
add_menu_page(
|
||||
'KTC Settings',
|
||||
'KTC Clock',
|
||||
'manage_options',
|
||||
'ktc-settings',
|
||||
array( 'KTC_Admin', 'render_settings_content' ),
|
||||
'dashicons-clock',
|
||||
85
|
||||
);
|
||||
|
||||
// 2. Register Settings
|
||||
register_setting( 'ktc_settings_group', 'ktc_timezone' );
|
||||
register_setting( 'ktc_settings_group', 'ktc_week_start' );
|
||||
register_setting( 'ktc_settings_group', 'ktc_alert_threshold', ['type' => 'integer', 'default' => 12] );
|
||||
register_setting( 'ktc_settings_group', 'ktc_enable_teams', ['type' => 'boolean', 'default' => 0] );
|
||||
register_setting( 'ktc_settings_group', 'ktc_teams_webhook', ['type' => 'string'] );
|
||||
|
||||
// 3. Section
|
||||
add_settings_section(
|
||||
'ktc_main_section',
|
||||
'Core Configuration',
|
||||
'__return_false',
|
||||
'ktc-settings'
|
||||
);
|
||||
|
||||
// 4. Fields - Triple check that these method names exist in this class
|
||||
add_settings_field(
|
||||
'ktc_timezone_field',
|
||||
'Timezone',
|
||||
array( __CLASS__, 'render_timezone_field' ),
|
||||
'ktc-settings',
|
||||
'ktc_main_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'ktc_alert_threshold_field',
|
||||
'Zombie Alert Threshold (Hours)',
|
||||
array( __CLASS__, 'render_threshold_field' ),
|
||||
'ktc-settings',
|
||||
'ktc_main_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'ktc_teams_config_field',
|
||||
'MS Teams Integration',
|
||||
array( __CLASS__, 'render_teams_fields' ),
|
||||
'ktc-settings',
|
||||
'ktc_main_section'
|
||||
);
|
||||
}
|
||||
|
||||
public static function render_settings_content() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>Krista Time Clock Settings</h1>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields( 'ktc_settings_group' );
|
||||
do_settings_sections( 'ktc-settings' );
|
||||
submit_button();
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
<?php }
|
||||
|
||||
/**
|
||||
* Renders the Threshold numeric input
|
||||
*/
|
||||
public static function render_threshold_field() {
|
||||
$val = get_option( 'ktc_alert_threshold', 12 );
|
||||
echo '<input type="number" name="ktc_alert_threshold" value="' . esc_attr( $val ) . '" class="small-text"> ';
|
||||
echo '<p class="description">Hours before a shift is flagged as a "Zombie Shift".</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the Teams Toggle and Webhook URL
|
||||
*/
|
||||
public static function render_teams_fields() {
|
||||
$enabled = get_option( 'ktc_enable_teams', 0 );
|
||||
$webhook = get_option( 'ktc_teams_webhook', '' );
|
||||
?>
|
||||
<label>
|
||||
<input type="checkbox" name="ktc_enable_teams" value="1" <?php checked( $enabled, 1 ); ?>>
|
||||
Enable Teams Notifications
|
||||
</label>
|
||||
<br><br>
|
||||
<input type="text" name="ktc_teams_webhook" value="<?php echo esc_attr( $webhook ); ?>" class="regular-text" placeholder="https://outlook.office.com/webhook/...">
|
||||
<p class="description">Enter your Microsoft Teams Incoming Webhook URL.</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function render_timezone_field() {
|
||||
$current_tz = get_option( 'ktc_timezone', 'America/Chicago' );
|
||||
$tz_list = DateTimeZone::listIdentifiers();
|
||||
?>
|
||||
<select name="ktc_timezone">
|
||||
<?php foreach ( $tz_list as $tz ) : ?>
|
||||
<option value="<?php echo esc_attr( $tz ); ?>" <?php selected( $current_tz, $tz ); ?>>
|
||||
<?php echo esc_html( $tz ); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="description">This defines the legal "Source of Truth" for all timestamps, bypassing server or WP site drift.</p>
|
||||
<?php }
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user