?php /** * Plugin Name: Custom Appointments Scheduler (CAS) * Description: Simple shortcode-based scheduler with morning/afternoon slots, 15-min granularity, and block-out days. * Version: 1.0.0 * Author: ChatGPT */ if (!defined('ABSPATH')) exit; /** * Register custom post type for appointments */ add_action('init', function () { register_post_type('cas_appointment', [ 'labels' = [ 'name' => 'Appointments', 'singular_name' => 'Appointment', ], 'public' => false, 'show_ui' => true, 'menu_icon' => 'dashicons-calendar-alt', 'supports' => ['title', 'custom-fields'], ]); }); /** * Admin settings page to manage blocked dates */ add_action('admin_menu', function () { add_options_page('CAS Scheduler', 'CAS Scheduler', 'manage_options', 'cas-scheduler', 'cas_render_settings_page'); }); function cas_render_settings_page() { if (!current_user_can('manage_options')) return; if (isset($_POST['cas_blocked_dates_nonce']) && wp_verify_nonce($_POST['cas_blocked_dates_nonce'], 'cas_blocked_dates')) { $dates_raw = isset($_POST['cas_blocked_dates']) ? wp_unslash($_POST['cas_blocked_dates']) : ''; // Normalize to CSV of YYYY-MM-DD $dates = array_filter(array_map('trim', preg_split('/[s,]+/', $dates_raw))); $clean = []; foreach ($dates as $d) { $t = strtotime($d); if ($t) $clean[] = date('Y-m-d', $t); } update_option('cas_blocked_dates', implode(',', array_unique($clean))); echo '
'; } $blocked = get_option('cas_blocked_dates', ''); ?>
CAS Scheduler
Insert on a page: [cas_scheduler]
?php } /** * Shortcode to render scheduler UI * Attributes (all optional): * days="mon,tue,wed,thu,fri" * morning_start="09:00" morning_end="12:00" morning_capacity="1" * afternoon_start="13:00" afternoon_end="17:00" afternoon_capacity="1" * slot_length="60" step="15" max_per_day="2" * title="Schedule an Appointment" */ add_shortcode('cas_scheduler', function ($atts) { $a = shortcode_atts([ 'days' = 'mon,tue,wed,thu,fri', 'morning_start' => '09:00', 'morning_end' => '12:00', 'morning_capacity' => '1', 'afternoon_start' => '13:00', 'afternoon_end' => '17:00', 'afternoon_capacity' => '1', 'slot_length' => '60', 'step' => '15', 'max_per_day' => '2', 'title' => 'Schedule an Appointment', ], $atts, 'cas_scheduler'); $nonce = wp_create_nonce('cas_public'); // public-facing nonce $rest_base = esc_url_raw( rest_url('cas/v1') ); ob_start(); ?>