Constants
3 weeks ago
Accordion.php
1 week ago
Alert.php
1 week ago
AttachmentCard.php
1 week ago
Avatar.php
1 week ago
Badge.php
1 week ago
BaseComponent.php
3 weeks ago
Button.php
1 week ago
ConfirmationModal.php
1 week ago
CourseFilter.php
1 week ago
DateFilter.php
1 week ago
DropdownFilter.php
1 week ago
EmptyState.php
1 week ago
FileUploader.php
1 week ago
InputField.php
1 week ago
Modal.php
1 week ago
Nav.php
1 week ago
Pagination.php
1 week ago
Popover.php
1 week ago
PreviewTrigger.php
1 week ago
Progress.php
1 week ago
SearchFilter.php
1 week ago
Sorting.php
1 week ago
StarRating.php
1 week ago
StarRatingInput.php
1 week ago
StatusSelect.php
1 week ago
SvgIcon.php
1 week ago
Table.php
1 week ago
Tabs.php
1 week ago
Tooltip.php
1 week ago
WPEditor.php
1 week ago
StatusSelect.php
209 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Tutor Component: StatusSelect |
| 4 | * |
| 5 | * Provides a fluent builder for rendering status selection dropdowns. |
| 6 | * Direct replacement for the legacy select-with-icon. |
| 7 | * |
| 8 | * @package Tutor\Components |
| 9 | * @author Themeum |
| 10 | * @link https://themeum.com |
| 11 | * @since 4.0.0 |
| 12 | */ |
| 13 | |
| 14 | namespace Tutor\Components; |
| 15 | |
| 16 | defined( 'ABSPATH' ) || exit; |
| 17 | |
| 18 | use TUTOR\Icon; |
| 19 | |
| 20 | /** |
| 21 | * StatusSelect Component Class. |
| 22 | * |
| 23 | * Example usage: |
| 24 | * ```php |
| 25 | * // Basic status select for a course |
| 26 | * StatusSelect::make() |
| 27 | * ->options( array( |
| 28 | * 'publish' => array( 'label' => 'Published', 'variant' => 'success', 'icon' => Icon::CHECK_MARK ), |
| 29 | * 'pending' => array( 'label' => 'Pending', 'variant' => 'warning', 'icon' => Icon::CLOCK ), |
| 30 | * 'draft' => array( 'label' => 'Draft', 'variant' => 'default', 'icon' => Icon::EDIT ), |
| 31 | * ) ) |
| 32 | * ->selected( 'publish' ) |
| 33 | * ->action( 'tutor_change_course_status' ) |
| 34 | * ->data( array( 'id' => $course_id ) ) |
| 35 | * ->render(); |
| 36 | * |
| 37 | * // Order / enrollment status select |
| 38 | * StatusSelect::make() |
| 39 | * ->options( array( |
| 40 | * 'completed' => array( 'label' => 'Completed', 'variant' => 'success', 'icon' => Icon::CHECK_CIRCLE ), |
| 41 | * 'cancelled' => array( 'label' => 'Cancelled', 'variant' => 'error', 'icon' => Icon::CLOSE_CIRCLE ), |
| 42 | * 'processing' => array( 'label' => 'Processing','variant' => 'warning', 'icon' => Icon::CLOCK ), |
| 43 | * ) ) |
| 44 | * ->selected( 'processing' ) |
| 45 | * ->action( 'tutor_update_order_status' ) |
| 46 | * ->data( array( 'order_id' => $order_id ) ) |
| 47 | * ->render(); |
| 48 | * |
| 49 | * // Without an AJAX action (display only, no auto-update) |
| 50 | * StatusSelect::make() |
| 51 | * ->options( array( |
| 52 | * 'active' => array( 'label' => 'Active', 'variant' => 'success' ), |
| 53 | * 'inactive' => array( 'label' => 'Inactive', 'variant' => 'disabled' ), |
| 54 | * ) ) |
| 55 | * ->selected( 'active' ) |
| 56 | * ->render(); |
| 57 | * |
| 58 | * // With extra data attributes and HTML attrs on the wrapper |
| 59 | * StatusSelect::make() |
| 60 | * ->options( $status_options ) |
| 61 | * ->selected( $current_status ) |
| 62 | * ->action( 'tutor_change_status' ) |
| 63 | * ->data( array( 'id' => $item_id, 'nonce' => wp_create_nonce( 'tutor_nonce' ) ) ) |
| 64 | * ->attr( 'class', 'my-status-select' ) |
| 65 | * ->render(); |
| 66 | * |
| 67 | * // Retrieve HTML without echoing |
| 68 | * $html = StatusSelect::make()->options( $options )->selected( 'publish' )->get(); |
| 69 | * ``` |
| 70 | */ |
| 71 | class StatusSelect extends BaseComponent { |
| 72 | |
| 73 | /** |
| 74 | * List of options. |
| 75 | * |
| 76 | * [ 'value' => [ 'label' => 'Text', 'variant' => 'success', 'icon' => 'slug' ] ] |
| 77 | * |
| 78 | * @var array |
| 79 | */ |
| 80 | protected $options = array(); |
| 81 | |
| 82 | /** |
| 83 | * Selected value. |
| 84 | * |
| 85 | * @var string |
| 86 | */ |
| 87 | protected $selected = ''; |
| 88 | |
| 89 | /** |
| 90 | * AJAX action. |
| 91 | * |
| 92 | * @var string |
| 93 | */ |
| 94 | protected $action = ''; |
| 95 | |
| 96 | /** |
| 97 | * Additional data attributes. |
| 98 | * |
| 99 | * @var array |
| 100 | */ |
| 101 | protected $data = array(); |
| 102 | |
| 103 | /** |
| 104 | * Set options. |
| 105 | * |
| 106 | * @param array $options List of options. |
| 107 | * @return self |
| 108 | */ |
| 109 | public function options( array $options ): self { |
| 110 | $this->options = $options; |
| 111 | return $this; |
| 112 | } |
| 113 | |
| 114 | /** |
| 115 | * Set selected value. |
| 116 | * |
| 117 | * @param string $selected Selected value. |
| 118 | * @return self |
| 119 | */ |
| 120 | public function selected( string $selected ): self { |
| 121 | $this->selected = $selected; |
| 122 | return $this; |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * Set AJAX action. |
| 127 | * |
| 128 | * @param string $action AJAX action name. |
| 129 | * @return self |
| 130 | */ |
| 131 | public function action( string $action ): self { |
| 132 | $this->action = $action; |
| 133 | return $this; |
| 134 | } |
| 135 | |
| 136 | /** |
| 137 | * Set additional data attributes. |
| 138 | * |
| 139 | * @param array $data Key-value pairs for data attributes. |
| 140 | * @return self |
| 141 | */ |
| 142 | public function data( array $data ): self { |
| 143 | $this->data = array_merge( $this->data, $data ); |
| 144 | return $this; |
| 145 | } |
| 146 | |
| 147 | /** |
| 148 | * Get the component HTML. |
| 149 | * |
| 150 | * @return string |
| 151 | */ |
| 152 | public function get(): string { |
| 153 | $selected_option = $this->options[ $this->selected ] ?? null; |
| 154 | $current_variant = $selected_option['variant'] ?? 'default'; |
| 155 | |
| 156 | // Prepare Alpine.js props. |
| 157 | $alpine_props = wp_json_encode( |
| 158 | array( |
| 159 | 'selected' => $this->selected, |
| 160 | 'action' => $this->action, |
| 161 | 'data' => $this->data, |
| 162 | 'variants' => array_map( fn( $opt ) => $opt['variant'] ?? 'default', $this->options ), |
| 163 | ) |
| 164 | ); |
| 165 | |
| 166 | ob_start(); |
| 167 | ?> |
| 168 | <div |
| 169 | class="tutor-status-select tutor-status-select-<?php echo esc_attr( $current_variant ); ?>" |
| 170 | x-data="tutorStatusSelect(<?php echo esc_attr( $alpine_props ); ?>)" |
| 171 | :class="variantClasses" |
| 172 | <?php $this->render_attributes(); ?> |
| 173 | > |
| 174 | <div class="tutor-status-select-icon"> |
| 175 | <div class="tutor-status-select-icon-wrapper" x-show="!isLoading"> |
| 176 | <?php foreach ( $this->options as $value => $option ) : ?> |
| 177 | <?php if ( ! empty( $option['icon'] ) ) : ?> |
| 178 | <span x-show="selectedValue === '<?php echo esc_attr( $value ); ?>'" <?php echo $this->selected !== $value ? 'style="display: none;"' : ''; ?>> |
| 179 | <?php SvgIcon::make()->name( $option['icon'] )->render(); ?> |
| 180 | </span> |
| 181 | <?php endif; ?> |
| 182 | <?php endforeach; ?> |
| 183 | </div> |
| 184 | <span x-show="isLoading" style="display: none;"> |
| 185 | <?php SvgIcon::make()->name( Icon::SPINNER )->size( 14 )->attr( 'class', 'tutor-animate-spin' )->render(); ?> |
| 186 | </span> |
| 187 | </div> |
| 188 | |
| 189 | <select |
| 190 | x-model="selectedValue" |
| 191 | @change="updateStatus" |
| 192 | :disabled="isLoading" |
| 193 | > |
| 194 | <?php foreach ( $this->options as $value => $option ) : ?> |
| 195 | <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $this->selected, $value ); ?>> |
| 196 | <?php echo esc_html( $option['label'] ?? '' ); ?> |
| 197 | </option> |
| 198 | <?php endforeach; ?> |
| 199 | </select> |
| 200 | |
| 201 | <div class="tutor-status-select-arrow"> |
| 202 | <?php SvgIcon::make()->name( Icon::CHEVRON_DOWN_2 )->render(); ?> |
| 203 | </div> |
| 204 | </div> |
| 205 | <?php |
| 206 | return ob_get_clean(); |
| 207 | } |
| 208 | } |
| 209 |