first_name ); $last = trim( $user->last_name ); if ( $first || $last ) { return trim( $first . ' ' . $last ); } // Fallbacks if no first/last name if ( $user->display_name ) { return $user->display_name; } if ( $user->user_login ) { return $user->user_login; } if ( $user->user_email ) { return $user->user_email; } return $fallback; } function get_date_format() { return apply_filters('pickuppt_get_date_format', 'Y-m-d'); } function get_time_format() { return apply_filters('pickuppt_get_time_format', 'h:i A'); } function get_datetime_format() { return apply_filters('pickuppt_get_datetime_format', 'Y-m-d h:i A'); } # register settings function pickuppt_register_options_cb() { register_setting('pickuppt_general_settings', 'pickuppt_general_settings_group', array( 'sanitize_callback' => array($this, 'pickuppt_sanitize_general_settings'), ) ); do_action('pickuppt_register_options_cb'); } # sanitize settings function pickuppt_sanitize_general_settings( $input ) { if ( ! is_array( $input ) ) { return array(); } $output = array(); /** * Payment settings */ $output['payment_link'] = isset( $input['payment_link'] )? esc_url_raw( $input['payment_link'] ): ''; $output['qr_code_link'] = isset( $input['qr_code_link'] ) ? esc_url_raw( $input['qr_code_link'] ) : ''; /* * General settings. */ $output['logo_url'] = isset( $input['logo_url'] ) ? esc_url_raw( $input['logo_url'] ) : ''; $output['auto_generate_title'] = ! empty( $input['auto_generate_title'] ) ? 'on' : ''; $output['is_alpha_numeric'] = ! empty( $input['is_alpha_numeric'] ) ? 'on' : ''; $output['title_length'] = isset( $input['title_length'] ) ? absint( $input['title_length'] ) : 0; $output['title_prefix'] = isset( $input['title_prefix'] )? sanitize_text_field( $input['title_prefix'] ): ''; $output['title_suffix'] = isset( $input['title_suffix'] )? sanitize_text_field( $input['title_suffix'] ): ''; $output['items'] = isset( $input['items'] )? pickuppt_sanitize_csv( $input['items'] ): ''; $output['statuses'] = isset( $input['statuses'] )? pickuppt_sanitize_csv( $input['statuses'] ): ''; /* * Colors. */ $output['theme_color'] = isset( $input['theme_color'] ) ? sanitize_hex_color( $input['theme_color'] ) : ''; foreach ( pickuppt_statuses() as $status ) { $slugified_status = pickuppt_slugify($status) . '_color'; $output[ $slugified_status ] = isset( $input[ $slugified_status ] ) ? sanitize_hex_color( $input[ $slugified_status ] ) : ''; } /* * Status settings. */ $status_fields = array( 'default_status', 'rescheduled_status', 'driver_assigned_status', 'picked_up_status', 'completed_status', 'cancelled_status', 'flagged_status', 'awaiting_reassignment_status', 'pending_payment_status', 'payment_confirmed_status' ); foreach ( $status_fields as $field ) { $output[ $field ] = isset( $input[ $field ] ) ? sanitize_text_field( $input[ $field ] ) : ''; } /* * Other settings. */ $output['weight_unit'] = isset( $input['weight_unit'] )? sanitize_text_field( $input['weight_unit'] ): ''; $output['time_slot_interval'] = isset( $input['time_slot_interval'] )? absint( $input['time_slot_interval'] ): 0; $output['max_time_slot_cap'] = isset( $input['max_time_slot_cap'] ) ? absint( $input['max_time_slot_cap'] ): 0; $output['pickuppt_sender_email'] = isset( $input['pickuppt_sender_email'] )? sanitize_email( $input['pickuppt_sender_email'] ): ''; $output['gmaps_api_key'] = isset( $input['gmaps_api_key'] )? sanitize_text_field( $input['gmaps_api_key'] ): ''; /* * Destination structure. */ $output['custom_destination'] = ! empty( $input['custom_destination'] ) ? 'on' : ''; $output['warehouses'] = array(); if ( isset( $input['warehouses'] ) && is_array( $input['warehouses'] ) ) { foreach ( $input['warehouses'] as $holiday ) { if ( ! is_array( $holiday ) ) { continue; } $output['warehouses'][] = array( 'warehouse_name' => isset( $holiday['warehouse_name'] )? sanitize_text_field( $holiday['warehouse_name'] ): '', 'warehouse_address' => isset( $holiday['warehouse_address'] )? sanitize_text_field( $holiday['warehouse_address'] ): '', ); } } /* * Day offs. */ $output['day_offs'] = array(); if ( isset( $input['day_offs'] ) && is_array( $input['day_offs'] ) ) { foreach ( $input['day_offs'] as $day ) { $output['day_offs'][] = absint( $day ); } $output['day_offs'] = array_values( array_unique( $output['day_offs'] ) ); } /* * Holidays. */ $output['holidays'] = array(); if ( isset( $input['holidays'] ) && is_array( $input['holidays'] ) ) { foreach ( $input['holidays'] as $holiday ) { if ( ! is_array( $holiday ) ) { continue; } $output['holidays'][] = array( 'holiday_name' => isset( $holiday['holiday_name'] )? sanitize_text_field( $holiday['holiday_name'] ): '', 'holiday_date' => isset( $holiday['holiday_date'] )? sanitize_text_field( $holiday['holiday_date'] ): '', ); } } /* * Customer email settings. */ $output['email_subject'] = isset( $input['email_subject'] ) ? sanitize_text_field( $input['email_subject'] ) : ''; $output['email_from'] = isset( $input['email_from'] ) ? sanitize_email( $input['email_from'] ) : ''; $output['email_to'] = isset( $input['email_to'] ) ? pickuppt_sanitize_email_placeholders( $input['email_to'] ) : ''; $output['email_bc'] = isset( $input['email_bc'] ) ? pickuppt_sanitize_email_placeholders( $input['email_bc'] ) : ''; $output['email_cc'] = isset( $input['email_cc'] ) ? pickuppt_sanitize_email_placeholders( $input['email_cc'] ) : ''; $output['email_body'] = isset( $input['email_body'] ) ? wp_kses_post( $input['email_body'] ) : ''; /* * Admin email settings. */ $output['admin_email_subject'] = isset( $input['admin_email_subject'] ) ? sanitize_text_field( $input['admin_email_subject'] ) : ''; $output['admin_email_from'] = isset( $input['admin_email_from'] ) ? sanitize_email( $input['admin_email_from'] ) : ''; $output['admin_email_to'] = isset( $input['admin_email_to'] ) ? pickuppt_sanitize_email_placeholders( $input['admin_email_to'] ) : ''; $output['admin_email_bc'] = isset( $input['admin_email_bc'] ) ? pickuppt_sanitize_email_placeholders( $input['admin_email_bc'] ) : ''; $output['admin_email_cc'] = isset( $input['admin_email_cc'] ) ? pickuppt_sanitize_email_placeholders( $input['admin_email_cc'] ) : ''; $output['admin_email_body'] = isset( $input['admin_email_body'] ) ? wp_kses_post( $input['admin_email_body'] ) : ''; /* * Appointment status email settings. */ $output['appt_email_subject'] = isset( $input['appt_email_subject'] ) ? sanitize_text_field( $input['appt_email_subject'] ) : ''; $output['appt_email_from'] = isset( $input['appt_email_from'] ) ? sanitize_email( $input['appt_email_from'] ) : ''; $output['appt_email_to'] = isset( $input['appt_email_to'] ) ? pickuppt_sanitize_email_placeholders( $input['appt_email_to'] ) : ''; $output['appt_email_bc'] = isset( $input['appt_email_bc'] ) ? pickuppt_sanitize_email_placeholders( $input['appt_email_bc'] ) : ''; $output['appt_email_cc'] = isset( $input['appt_email_cc'] ) ? pickuppt_sanitize_email_placeholders( $input['appt_email_cc'] ) : ''; $output['appt_email_body'] = isset( $input['appt_email_body'] ) ? wp_kses_post( $input['appt_email_body'] ) : ''; $hooked_output = apply_filters( 'pickuppt_settings_sanitized_output', $output, $input ); return $hooked_output; } /** * Get and sanitize URL parameters safely for admin and front-end views. */ public function pickuppt_get_all_url_param_values() { // Admin parameters: Ensure user is in admin and has proper permissions if ( is_admin() ) { if ( ! current_user_can( 'manage_options' ) ) { return; } $this->url_param_post_type = isset( $_GET['post_type'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type'] ) ) : ''; $this->url_param_page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; $this->url_param_pu_assigned_driver_id = isset( $_GET['pu_assigned_driver_id'] ) ? absint( wp_unslash( $_GET['pu_assigned_driver_id'] ) ) : 0; $this->url_param_action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : ''; $this->url_param_post = isset( $_GET['post'] ) ? absint( wp_unslash( $_GET['post'] ) ) : 0; } // Front-end / public parameters (accessible to guests or users) if ( isset( $_GET['pickuppt'] ) ) { $this->url_param_pickuppt = sanitize_text_field( wp_unslash( $_GET['pickuppt'] ) ); } else { $this->url_param_pickuppt = ''; } } # register custom post type function pickuppt_register_cpt() { $labels = array( 'name' => _x('All Appointments', 'Appointment', 'pickuppointment'), 'singular_name' => _x('Appointment', 'Appointment', 'pickuppointment'), 'menu_name' => esc_html__('PickUppointments', 'pickuppointment'), 'all_items' => esc_html__('All Appointments', 'pickuppointment'), 'view_item' => esc_html__('View Appointments', 'pickuppointment'), 'add_new_item' => esc_html__('Add New', 'pickuppointment'), 'add_new' => esc_html__('Add Appointment', 'pickuppointment'), 'edit_item' => esc_html__('Edit Appointment', 'pickuppointment'), 'update_item' => esc_html__('Update Appointment', 'pickuppointment'), 'search_items' => esc_html__('Search', 'pickuppointment'), 'not_found' => esc_html__('No appointments found.', 'pickuppointment'), 'not_found_in_trash' => esc_html__('No appointments found in trash.', 'pickuppointment') ); $supports = array( 'title', 'author', 'thumbnail', 'revisions' ); $args = array( 'label' => esc_html__('Appointments', 'pickuppointment'), 'description' => esc_html__('Appointments', 'pickuppointment'), 'labels' => $labels, 'supports' => $supports, 'taxonomies' => array( PICKUPPOINTMENT_POST_TYPE, 'post_tag' ), 'menu_icon' => 'dashicons-text-page', 'hierarchical' => true, 'public' => false, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => true, 'show_in_admin_bar' => true, 'can_export' => true, 'has_archive' => false, 'exclude_from_search' => true, 'publicly_queryable' => false, 'capability_type' => 'post' ); register_post_type(PICKUPPOINTMENT_POST_TYPE, $args); $cat_labels = array( 'name' => _x('Categories', 'Category', 'pickuppointment'), 'singular_name' => _x('Category', 'Category', 'pickuppointment'), 'search_items' => esc_html__('Search Category', 'pickuppointment'), 'all_items' => esc_html__('All Categories', 'pickuppointment'), 'parent_item' => esc_html__('Parent Category', 'pickuppointment'), 'parent_item_colon' => esc_html__('Parent Category:', 'pickuppointment'), 'edit_item' => esc_html__('Edit Category', 'pickuppointment'), 'update_item' => esc_html__('Update Category', 'pickuppointment'), 'add_new_item' => esc_html__('Add New', 'pickuppointment'), 'new_item_name' => esc_html__('New Category Name', 'pickuppointment'), 'menu_name' => esc_html__('Category', 'pickuppointment') ); $cat_args = array( 'hierarchical' => true, 'labels' => $cat_labels, 'show_ui' => true, 'show_admin_column' => true, 'query_var' => true ); register_taxonomy('pickuppointment_cat', array( PICKUPPOINTMENT_POST_TYPE ), $cat_args); // add a new role foreach(pickuppt_system_roles() as $role_slug => $role_name) { if(!get_role($role_slug)) { add_role($role_slug, $role_name, array()); } } } function pickuppt_admin_menu_page_cb() { $parent = 'edit.php?post_type=' . PICKUPPOINTMENT_POST_TYPE; add_submenu_page( $parent, __( 'Calendar', 'pickuppointment' ), __( 'Calendar', 'pickuppointment' ), 'manage_options', 'pickuppointments-page', array( $this, 'pickuppt_admin_dashboard_page_cb' ) ); add_submenu_page( $parent, __( 'Settings', 'pickuppointment' ), __( 'Settings', 'pickuppointment' ), 'manage_options', 'pickuppointment-settings-page', array( $this, 'pickuppt_admin_settings_page_cb' ) ); } function pickuppt_admin_dashboard_page_cb() { ?>
url_param_page; $pickuppt = $this->url_param_pickuppt; if($page === 'pickuppointments-page' || $pickuppt === 'calendar') { require_once(pickuppt_include_template('calendar-script.tpl')); } } function pickuppt_admin_wp_enqueue_scripts_cb() { global $post; if(!$post) { return; } $is_pickuppointment_public_form_present = false; if ( $post && has_shortcode( $post->post_content, 'pickuppointment_form_public' ) ) { $is_pickuppointment_public_form_present = true; } $dynamic_version = PICKUPPOINTMENT_VERSION . time(); $page = $this->url_param_page; $pickuppt = $this->url_param_pickuppt; if(in_array($page, pickuppt_page_slugs_for_assets()) || $pickuppt === 'calendar') { wp_enqueue_style('pickuppt-bootstrap-css', PICKUPPOINTMENT_URL . 'lib/bootstrap.min.css', array(), PICKUPPOINTMENT_VERSION); if( $page === 'pickuppointments-page' || $pickuppt === 'calendar' ) { wp_enqueue_script('pickuppt-popper-min-js', PICKUPPOINTMENT_URL . 'lib/popper.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); wp_enqueue_script('pickuppt-fullcalendar-scripts', PICKUPPOINTMENT_URL . 'lib/fullcalendar-6.1.17/dist/index.global.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); wp_enqueue_script('pickuppt-calendar-scripts', PICKUPPOINTMENT_URL . 'admin/assets/js/calendar-scripts.js', array('jquery'), $dynamic_version, true); $calendar_scripts_localization = array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'puAllAppointments' => pickuppt_all_appointments(true), 'puCanUpdate' => pickuppt_can_update() ? true : false, 'pickupptGetTransInfoNonce' => wp_create_nonce('pickupptGetTransInfoNonce'), 'pickupptUpdateTransNonce' => wp_create_nonce('pickupptUpdateTransNonce'), 'pickupptGetCurrentMonthYearApptsNonce' => wp_create_nonce('pickupptGetCurrentMonthYearApptsNonce') ); wp_localize_script('pickuppt-calendar-scripts', 'pickupptCalendarScripts', $calendar_scripts_localization); } } $calendar_day_offs = pickuppt_get_general_setting('day_offs') ?: array(); $calendar_holidays = pickuppt_get_general_setting('holidays') ?: array(); $calendar_holiday_dates = array_column( $calendar_holidays, 'holiday_date' ); $calendar_day_offs_json = json_encode( $calendar_day_offs ); $calendar_holiday_dates_json = json_encode( $calendar_holiday_dates ); wp_enqueue_script('pickuppt-repeater-js', PICKUPPOINTMENT_URL . 'lib/repeater.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); if ($post && has_shortcode($post->post_content, 'pickuppointment_form_public')) { wp_enqueue_style('pickuppt-timepicker-css', PICKUPPOINTMENT_URL . 'lib/timepicker/jquery.timepicker.min.css', array(), PICKUPPOINTMENT_VERSION); wp_enqueue_style('pickuppt-public-form-css', PICKUPPOINTMENT_URL . 'admin/assets/css/public-form-styles.css', array(), $dynamic_version); wp_enqueue_script('pickuppt-timepicker-js', PICKUPPOINTMENT_URL . 'lib/timepicker/jquery.timepicker.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); wp_enqueue_script('pickuppt-popper-min-js', PICKUPPOINTMENT_URL . 'lib/popper.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); wp_enqueue_script('pickuppt-fullcalendar-scripts', PICKUPPOINTMENT_URL . 'lib/fullcalendar-6.1.17/dist/index.global.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); wp_enqueue_script('pickuppt-public-form-js', PICKUPPOINTMENT_URL . 'admin/assets/js/public-form-scripts.js', array('jquery'), $dynamic_version, true); $localization = array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'calendarDayoffsJson' => $calendar_day_offs_json, 'calendarHolidayDatesJson' => $calendar_holiday_dates_json, 'pickupptPublicFormNonce' => wp_create_nonce('pu_submit_public_appointment'), 'pickupptPublicFormTimeslotInterval' => pickuppt_time_slot_interval() ); wp_localize_script('pickuppt-public-form-js', 'pickupptPublicForm', $localization); } /** * global styles */ wp_enqueue_style('pickuppointment-global-styles', PICKUPPOINTMENT_URL . 'admin/assets/css/global-styles.css', array(), $dynamic_version); /** * calendar styles */ wp_register_style( 'pickuppointment-calendary-styles', false, array(), PICKUPPOINTMENT_VERSION ); wp_enqueue_style( 'pickuppointment-calendary-styles' ); $base_color = pickuppt_get_general_setting('theme_color') ?: '#0073aa'; $dynamic_css = ' /* =============================== FullCalendar Custom Styling Dynamic Theme Color Scoped to #pickuppt-calendar =============================== */ #pickuppt-calendar { font-family: "Poppins", "Segoe UI", Arial, sans-serif; background: ' . esc_html(pickuppt_color_shade_generator($base_color, 90)) . '; border: 1px solid ' . esc_html(pickuppt_color_shade_generator($base_color, 55)) . '; border-radius: 8px; font-size: 0.9rem !important; } /* Header Toolbar */ #pickuppt-calendar .fc-toolbar { background: ' . esc_html(pickuppt_color_shade_generator($base_color, 70)) . '; border-bottom: 1px solid ' . esc_html(pickuppt_color_shade_generator($base_color, 55)) . '; border-radius: 8px 8px 0 0; padding: 0.5rem 1rem; } #pickuppt-calendar .fc-toolbar-title { font-size: 1.25rem; font-weight: 600; color: ' . esc_html(pickuppt_color_shade_generator($base_color, -35)) . '; } /* Buttons */ #pickuppt-calendar .fc-button { background: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . '; color: #fff; border: none; border-radius: 4px; font-size: 0.9rem; transition: background 0.2s ease, transform 0.1s ease; } #pickuppt-calendar .fc-button:hover { background: ' . esc_html(pickuppt_color_shade_generator($base_color, -20)) . '; transform: translateY(-1px); } #pickuppt-calendar .fc-button-primary:not(:disabled).fc-button-active, #pickuppt-calendar .fc-button-primary:not(:disabled):active { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, -35)) . '; } /* Calendar Grid */ #pickuppt-calendar .fc-daygrid-day { border: 1px style ' . esc_html(pickuppt_color_shade_generator($base_color, 65)) . '; background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 90)) . '; transition: background 0.15s ease; } #pickuppt-calendar .fc-daygrid-day:hover { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 75)) . '; } #pickuppt-calendar .fc-daygrid-day.fc-day-today { background: ' . esc_html(pickuppt_color_shade_generator($base_color, 45)) . '; border-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . '; } /* Day Numbers */ #pickuppt-calendar .fc-daygrid-day-number { font-weight: 500; color: ' . esc_html(pickuppt_color_shade_generator($base_color, -35)) . '; } /* Events */ #pickuppt-calendar .fc-event { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . '; border: none; color: #fff; border-radius: 4px; font-size: 0.85rem; transition: background 0.2s ease; } #pickuppt-calendar .fc-event:hover { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, -20)) . '; } /* Scrollbar & List View */ #pickuppt-calendar .fc-scroller { scrollbar-width: thin; scrollbar-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . ' ' . esc_html(pickuppt_color_shade_generator($base_color, 70)) . '; } #pickuppt-calendar .fc-scroller::-webkit-scrollbar { width: 6px; } #pickuppt-calendar .fc-scroller::-webkit-scrollbar-thumb { background: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . '; border-radius: 3px; } #pickuppt-calendar .fc-list-event { border-bottom: 1px solid ' . esc_html(pickuppt_color_shade_generator($base_color, 65)) . '; } #pickuppt-calendar .fc-list-event:hover { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 75)) . '; } .tooltip-inner { text-align: left !important; } /* Responsive */ @media (max-width: 768px) { #pickuppt-calendar .fc-toolbar { flex-wrap: wrap; text-align: center; } #pickuppt-calendar .fc-toolbar-title { width: 100%; margin-bottom: 0.5rem; } }'; wp_add_inline_style( 'pickuppointment-calendary-styles', $dynamic_css ); /** * dynamic timeslot script */ wp_enqueue_script('pickuppointment-dynamic-timeslot-scripts', PICKUPPOINTMENT_URL . 'admin/assets/js/dynamic-timeslot.js', array('jquery'), $dynamic_version, true); $pickuppointment_dynamic_timeslot_localization = array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'timeSlotInterval' => pickuppt_time_slot_interval(), 'pickupptDynamicTimeslotNonce' => wp_create_nonce( 'pickupptDynamicTimeslotNonce' ) ); wp_localize_script('pickuppointment-dynamic-timeslot-scripts', 'pickuppointmentDynamicTimeslotObj', $pickuppointment_dynamic_timeslot_localization); /** * charges script */ wp_enqueue_script('pickuppointment-charges-scripts', PICKUPPOINTMENT_URL . 'admin/assets/js/charges-scripts.js', array('jquery'), $dynamic_version, true); $pickuppointment_charges_localization = array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'deleteItemWarning' => __( 'Are you sure you want to delete this item?', 'pickuppointment' ), 'pickupptSaveOrderChargesNonce' => wp_create_nonce( 'pickupptSaveOrderChargesNonce' ), 'pickupptGetOrderChargesNonce' => wp_create_nonce( 'pickupptGetOrderChargesNonce' ) ); wp_localize_script('pickuppointment-charges-scripts', 'pickuppointmentChargesObj', $pickuppointment_charges_localization); /** * google maps api script */ $gmaps_api_key = pickuppt_get_general_setting('gmaps_api_key'); if( !empty( $gmaps_api_key ) ) { $pickuppt_can_load_gmaps_api = false; if( $this->url_param_page === 'pickuppointment-settings-page' ) { $pickuppt_can_load_gmaps_api = true; } if( 'pickuppointment' == $this->url_param_post_type ) { $pickuppt_can_load_gmaps_api = true; } global $post; if ( is_singular() && is_a( $post, 'WP_Post' ) ) { if ( has_shortcode( $post->post_content, 'pickuppointment_form_public' ) ) { $pickuppt_can_load_gmaps_api = true; } $page_template = get_post_meta($post->ID, '_wp_page_template', true); if('pu-hub-template.php' === $page_template && is_user_logged_in()) { $pickuppt_can_load_gmaps_api = true; } } $pickuppt_can_load_gmaps_api = apply_filters( 'pickuppt_can_load_gmaps_api', $pickuppt_can_load_gmaps_api ); if( $pickuppt_can_load_gmaps_api ) { $maps_url = add_query_arg( array( 'key' => $gmaps_api_key, 'libraries' => 'places', 'callback' => 'pickuppointmentInitAutocomplete', ), 'https://maps.googleapis.com/maps/api/js' ); wp_register_script( 'pickuppointment-google-maps', $maps_url, array('jquery'), PICKUPPOINTMENT_VERSION, array( 'strategy' => 'async', 'in_footer' => true ) ); $inline_script = ' function pickuppointmentInitAutocomplete() { jQuery(function($) { $(".pickuppointment-autocomplete").each(function() { const autocomplete = new google.maps.places.Autocomplete( this, { fields: ["address_components", "formatted_address"] } ); }); }); }'; wp_add_inline_script( 'pickuppointment-google-maps', $inline_script, 'before' ); wp_enqueue_script( 'pickuppointment-google-maps' ); } } } # add meta boxes function pickuppt_add_mtb() { $action = $this->url_param_action; add_meta_box( 'pickuppt_add_mtb_customer_info', pickuppt_customer_information_label(), array($this, 'pickuppt_add_mtb_customer_info'), PICKUPPOINTMENT_POST_TYPE, 'normal' ); add_meta_box( 'pickuppt_add_mtb_item_info', pickuppt_item_information_label(), array($this, 'pickuppt_add_mtb_item_info'), PICKUPPOINTMENT_POST_TYPE, 'normal' ); add_meta_box( 'pickuppt_add_mtb_pickup_info', pickuppt_pickup_information_label(), array($this, 'pickuppt_add_mtb_pickup_info'), PICKUPPOINTMENT_POST_TYPE, 'normal' ); if($action === 'edit') { add_meta_box( 'pickuppt_history_info', pickuppt_appt_history_label(), array($this, 'pickuppt_history_info'), PICKUPPOINTMENT_POST_TYPE, 'normal' ); } do_action('pickuppt_add_mtb', $this); } # customer info section callback function pickuppt_add_mtb_customer_info($post) { $post_id = $post->ID; require_once(pickuppt_include_template('mtb-customer-info')); } # pickup info section callback function pickuppt_add_mtb_pickup_info($post) { $post_id = $post->ID; require_once(pickuppt_include_template('mtb-pickup-info')); } # items info section callback function pickuppt_add_mtb_item_info($post) { $post_id = $post->ID; require_once(pickuppt_include_template('mtb-item-info')); } # history information on edit page function pickuppt_history_info($post) { $post_id = $post->ID; $pickuppt_get_appt_history = pickuppt_get_appt_history($post_id); require_once(pickuppt_include_template('mtb-history-info')); } function pickuppt_save_custom_mtb($post_id) { // Prevent recursion / auto-saves if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // Check post type (run only for your CPT) if (get_post_type($post_id) !== PICKUPPOINTMENT_POST_TYPE) { return; } // Check user permissions if (!current_user_can('edit_post', $post_id)) { return; } // check nonce if (!isset($_POST['pickuppt_meta_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['pickuppt_meta_nonce'])), 'pickuppt_save_meta')) { return; } if($_POST && is_array($_POST)) { $first_status = ''; $old_status = get_post_meta($post_id, 'pickuppt_status', true); // get email $pickuppt_email = sanitize_text_field(wp_unslash($_POST['pickuppt_email'] ?? '')); # save customer info fields foreach(pickuppt_customer_info_fields() as $k => $v) { $customer_info_val = sanitize_text_field(wp_unslash(($_POST[$k] ?? '') ?: '')); update_post_meta($post_id, $k, $customer_info_val); } # save pickup info fields foreach(pickuppt_pickup_info_fields() as $k => $v) { $pickup_info_val = sanitize_text_field(wp_unslash(($_POST[$k] ?? '') ?: '')); if($k === 'pickuppt_status') { $first_status = $pickup_info_val; } update_post_meta($post_id, $k, $pickup_info_val); } # save pickup info fields foreach(pickuppt_items_info_fields() as $k => $v) { $item_info_val = sanitize_text_field(wp_unslash(($_POST[$k] ?? '') ?: '')); update_post_meta($post_id, $k, $item_info_val); } // assign the appointment if user email exists on the system if($pickuppt_email) { $user_data = get_user_by('email', $pickuppt_email); if($user_data && is_object($user_data)) { update_post_meta($post_id, 'pickuppt_appt_owner', $user_data->ID); } } # save history if($first_status) { pickuppt_save_history($post_id, $old_status, $first_status); $pickuppt_history = maybe_unserialize(get_post_meta($post_id, 'pickuppt_history', true)); if(is_array($pickuppt_history) && count($pickuppt_history) === 1) { pickuppt_send_appt_emails($post_id); } else { pickuppt_send_appt_email($post_id); } $sanitized_form_data = pickuppt_sanitize_array( wp_unslash( $_POST ) ); do_action('pickuppt_after_save_admin_appt', $post_id, $sanitized_form_data, $first_status); } } } function pickuppt_enqueue_general_assets() { $can_enqueue_admin_assets = false; $can_enqueue_additional_assets = false; $post_type = $this->url_param_post_type; $post = $this->url_param_post; $action = $this->url_param_action; $page = $this->url_param_page; $pickuppt = $this->url_param_pickuppt; $is_auto_generate_title = pickuppt_get_general_setting('auto_generate_title') ?: false; $generated_title = pickuppt_generate_title(); $dynamic_version = PICKUPPOINTMENT_VERSION . time(); if(in_array($page, pickuppt_page_slugs_for_assets()) || $pickuppt === 'calendar') { wp_enqueue_style('pickuppt-bootstrap-css', PICKUPPOINTMENT_URL . 'lib/bootstrap.min.css', array(), PICKUPPOINTMENT_VERSION); if( $page === 'pickuppointments-page' || $pickuppt === 'calendar' ) { wp_enqueue_script('pickuppt-popper-min-js', PICKUPPOINTMENT_URL . 'lib/popper.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); wp_enqueue_script('pickuppt-fullcalendar-scripts', PICKUPPOINTMENT_URL . 'lib/fullcalendar-6.1.17/dist/index.global.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); wp_enqueue_script('pickuppt-calendar-scripts', PICKUPPOINTMENT_URL . 'admin/assets/js/calendar-scripts.js', array('jquery'), $dynamic_version, true); $calendar_scripts_localization = array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'puAllAppointments' => pickuppt_all_appointments(true), 'puCanUpdate' => pickuppt_can_update() ? true : false, 'pickupptGetTransInfoNonce' => wp_create_nonce('pickupptGetTransInfoNonce'), 'pickupptUpdateTransNonce' => wp_create_nonce('pickupptUpdateTransNonce'), 'pickupptGetCurrentMonthYearApptsNonce' => wp_create_nonce('pickupptGetCurrentMonthYearApptsNonce') ); wp_localize_script('pickuppt-calendar-scripts', 'pickupptCalendarScripts', $calendar_scripts_localization); } } if($post_type === PICKUPPOINTMENT_POST_TYPE) { $can_enqueue_admin_assets = true; } if(is_numeric($post) && $post > 0 && $action === 'edit') { $post_type = get_post_type($post); if($post_type === PICKUPPOINTMENT_POST_TYPE) { $can_enqueue_admin_assets = true; } } if($page === 'pickuppointments-page') { $can_enqueue_admin_assets = true; } $_can_enqueue_admin_assets = apply_filters('pickuppt_can_enqueue_admin_assets', $can_enqueue_admin_assets); $_can_enqueue_additional_assets = apply_filters('pickuppt_can_enqueue_additional_assets', $can_enqueue_additional_assets); if($page === 'pickuppointment-settings-page' || $_can_enqueue_admin_assets) { wp_enqueue_media(); wp_enqueue_style('pickuppt-jquery-ui-css', PICKUPPOINTMENT_URL . 'admin/assets/css/jquery-ui.css', array(), PICKUPPOINTMENT_VERSION); wp_enqueue_script('jquery-ui-tabs'); } wp_enqueue_script('jquery-ui-datepicker'); $calendar_day_offs = pickuppt_get_general_setting('day_offs') ?: array(); $calendar_holidays = pickuppt_get_general_setting('holidays') ?: array(); $calendar_holiday_dates = array_column( $calendar_holidays, 'holiday_date' ); $calendar_day_offs_json = json_encode( $calendar_day_offs ); $calendar_holiday_dates_json = json_encode( $calendar_holiday_dates ); $localization = array( 'datepickerDateFormat' => apply_filters('pickuppt_datepicker_date_format', 'yy-mm-dd'), 'calendarDayOffsJSON' => $calendar_day_offs_json, 'calendarHolidayDatesJSON' => $calendar_holiday_dates_json, 'ajaxUrl' => admin_url('admin-ajax.php'), 'emptyItemWarningMsg' => apply_filters('pickuppt_empty_item_warning_message', __('Please select at least one booking.', 'pickuppointment')), 'emptyDriverWarningMsg' => apply_filters('pickuppt_empty_driver_warning_message', __('Please select a driver.', 'pickuppointment')), 'driverAssignSuccessMsg' => apply_filters('pickuppt_driver_assign_success_message', __('Selected booking(s) have been assigned to driver.', 'pickuppointment')), 'deleteItemConfirmMsg' => apply_filters('pickuppt_delete_item_confirm_message', __('Are you sure you want to delete this item?', 'pickuppointment')), 'puDateFormat' => pickuppt_datepicker_format(), 'pickupptAssignAppointmentsToDriverNonce' => wp_create_nonce('pickupptAssignAppointmentsToDriverNonce'), 'pickupptSendPaymentLinkNonce' => wp_create_nonce('pickupptSendPaymentLinkNonce'), 'isAutoGenerateTitle' => $is_auto_generate_title, 'generatedTitle' => $generated_title, 'puTimeslotInterval' => pickuppt_time_slot_interval(), 'pickupptAction' => $action ); $dynamic_version = PICKUPPOINTMENT_VERSION . time(); if($_can_enqueue_admin_assets) { wp_enqueue_style('pickuppt-admin-styles', PICKUPPOINTMENT_URL . 'admin/assets/css/admin-styles.css', array(), $dynamic_version); wp_enqueue_style('pickuppt-admin-timepicker-css', PICKUPPOINTMENT_URL . 'lib/timepicker/jquery.timepicker.min.css', array(), PICKUPPOINTMENT_VERSION); wp_enqueue_script('pickuppt-admin-timepicker-js', PICKUPPOINTMENT_URL . 'lib/timepicker/jquery.timepicker.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); } wp_enqueue_script('pickuppt-admin-scripts', PICKUPPOINTMENT_URL . 'admin/assets/js/admin-scripts.js', array('jquery', 'jquery-ui-datepicker', 'jquery-ui-tabs'), $dynamic_version, true); wp_enqueue_script('pickuppt-repeater-js', PICKUPPOINTMENT_URL . 'lib/repeater.min.js', array('jquery'), PICKUPPOINTMENT_VERSION, true); wp_localize_script('pickuppt-admin-scripts', 'pickupptAdminAssets', $localization); /** * global styles */ wp_enqueue_style('pickuppointment-global-styles', PICKUPPOINTMENT_URL . 'admin/assets/css/global-styles.css', array(), $dynamic_version); /** * calendar styles */ wp_register_style( 'pickuppointment-calendary-styles', false, array(), PICKUPPOINTMENT_VERSION ); wp_enqueue_style( 'pickuppointment-calendary-styles' ); $base_color = pickuppt_get_general_setting('theme_color') ?: '#0073aa'; $dynamic_css = ' /* =============================== FullCalendar Custom Styling Dynamic Theme Color Scoped to #pickuppt-calendar =============================== */ #pickuppt-calendar { font-family: "Poppins", "Segoe UI", Arial, sans-serif; background: ' . esc_html(pickuppt_color_shade_generator($base_color, 90)) . '; border: 1px solid ' . esc_html(pickuppt_color_shade_generator($base_color, 55)) . '; border-radius: 8px; font-size: 0.9rem !important; } /* Header Toolbar */ #pickuppt-calendar .fc-toolbar { background: ' . esc_html(pickuppt_color_shade_generator($base_color, 70)) . '; border-bottom: 1px solid ' . esc_html(pickuppt_color_shade_generator($base_color, 55)) . '; border-radius: 8px 8px 0 0; padding: 0.5rem 1rem; } #pickuppt-calendar .fc-toolbar-title { font-size: 1.25rem; font-weight: 600; color: ' . esc_html(pickuppt_color_shade_generator($base_color, -35)) . '; } /* Buttons */ #pickuppt-calendar .fc-button { background: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . '; color: #fff; border: none; border-radius: 4px; font-size: 0.9rem; transition: background 0.2s ease, transform 0.1s ease; } #pickuppt-calendar .fc-button:hover { background: ' . esc_html(pickuppt_color_shade_generator($base_color, -20)) . '; transform: translateY(-1px); } #pickuppt-calendar .fc-button-primary:not(:disabled).fc-button-active, #pickuppt-calendar .fc-button-primary:not(:disabled):active { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, -35)) . '; } /* Calendar Grid */ #pickuppt-calendar .fc-daygrid-day { border: 1px style ' . esc_html(pickuppt_color_shade_generator($base_color, 65)) . '; background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 90)) . '; transition: background 0.15s ease; } #pickuppt-calendar .fc-daygrid-day:hover { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 75)) . '; } #pickuppt-calendar .fc-daygrid-day.fc-day-today { background: ' . esc_html(pickuppt_color_shade_generator($base_color, 45)) . '; border-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . '; } /* Day Numbers */ #pickuppt-calendar .fc-daygrid-day-number { font-weight: 500; color: ' . esc_html(pickuppt_color_shade_generator($base_color, -35)) . '; } /* Events */ #pickuppt-calendar .fc-event { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . '; border: none; color: #fff; border-radius: 4px; font-size: 0.85rem; transition: background 0.2s ease; } #pickuppt-calendar .fc-event:hover { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, -20)) . '; } /* Scrollbar & List View */ #pickuppt-calendar .fc-scroller { scrollbar-width: thin; scrollbar-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . ' ' . esc_html(pickuppt_color_shade_generator($base_color, 70)) . '; } #pickuppt-calendar .fc-scroller::-webkit-scrollbar { width: 6px; } #pickuppt-calendar .fc-scroller::-webkit-scrollbar-thumb { background: ' . esc_html(pickuppt_color_shade_generator($base_color, 0)) . '; border-radius: 3px; } #pickuppt-calendar .fc-list-event { border-bottom: 1px solid ' . esc_html(pickuppt_color_shade_generator($base_color, 65)) . '; } #pickuppt-calendar .fc-list-event:hover { background-color: ' . esc_html(pickuppt_color_shade_generator($base_color, 75)) . '; } .tooltip-inner { text-align: left !important; } /* Responsive */ @media (max-width: 768px) { #pickuppt-calendar .fc-toolbar { flex-wrap: wrap; text-align: center; } #pickuppt-calendar .fc-toolbar-title { width: 100%; margin-bottom: 0.5rem; } }'; wp_add_inline_style( 'pickuppointment-calendary-styles', $dynamic_css ); /** * dynamic timeslot script */ wp_enqueue_script('pickuppointment-dynamic-timeslot-scripts', PICKUPPOINTMENT_URL . 'admin/assets/js/dynamic-timeslot.js', array('jquery'), $dynamic_version, true); $pickuppointment_dynamic_timeslot_localization = array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'timeSlotInterval' => pickuppt_time_slot_interval(), 'pickupptDynamicTimeslotNonce' => wp_create_nonce( 'pickupptDynamicTimeslotNonce' ) ); wp_localize_script('pickuppointment-dynamic-timeslot-scripts', 'pickuppointmentDynamicTimeslotObj', $pickuppointment_dynamic_timeslot_localization); /** * charges script */ wp_enqueue_script('pickuppointment-charges-scripts', PICKUPPOINTMENT_URL . 'admin/assets/js/charges-scripts.js', array('jquery'), $dynamic_version, true); $pickuppointment_charges_localization = array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'deleteItemWarning' => __( 'Are you sure you want to delete this item?', 'pickuppointment' ), 'pickupptSaveOrderChargesNonce' => wp_create_nonce( 'pickupptSaveOrderChargesNonce' ), 'pickupptGetOrderChargesNonce' => wp_create_nonce( 'pickupptGetOrderChargesNonce' ) ); wp_localize_script('pickuppointment-charges-scripts', 'pickuppointmentChargesObj', $pickuppointment_charges_localization); /** * google maps api script */ $gmaps_api_key = pickuppt_get_general_setting('gmaps_api_key'); if( !empty( $gmaps_api_key ) ) { $pickuppt_can_load_gmaps_api = false; if( $this->url_param_page === 'pickuppointment-settings-page' ) { $pickuppt_can_load_gmaps_api = true; } if( 'pickuppointment' == $this->url_param_post_type ) { $pickuppt_can_load_gmaps_api = true; } global $post; if ( is_singular() && is_a( $post, 'WP_Post' ) ) { if ( has_shortcode( $post->post_content, 'pickuppointment_form_public' ) ) { $pickuppt_can_load_gmaps_api = true; } $page_template = get_post_meta($post->ID, '_wp_page_template', true); if('pu-hub-template.php' === $page_template && is_user_logged_in()) { $pickuppt_can_load_gmaps_api = true; } } $pickuppt_can_load_gmaps_api = apply_filters( 'pickuppt_can_load_gmaps_api', $pickuppt_can_load_gmaps_api ); if( $pickuppt_can_load_gmaps_api ) { $maps_url = add_query_arg( array( 'key' => $gmaps_api_key, 'libraries' => 'places', 'callback' => 'pickuppointmentInitAutocomplete', ), 'https://maps.googleapis.com/maps/api/js' ); wp_register_script( 'pickuppointment-google-maps', $maps_url, array('jquery'), PICKUPPOINTMENT_VERSION, array( 'strategy' => 'async', 'in_footer' => true ) ); $inline_script = ' function pickuppointmentInitAutocomplete() { jQuery(function($) { $(".pickuppointment-autocomplete").each(function() { const autocomplete = new google.maps.places.Autocomplete( this, { fields: ["address_components", "formatted_address"] } ); }); }); }'; wp_add_inline_script( 'pickuppointment-google-maps', $inline_script, 'before' ); wp_enqueue_script( 'pickuppointment-google-maps' ); } } } } $pickuppointment_class = new PickUppointment(); }