Constants
20 hours ago
Accordion.php
20 hours ago
Alert.php
20 hours ago
AttachmentCard.php
20 hours ago
Avatar.php
20 hours ago
Badge.php
20 hours ago
BaseComponent.php
20 hours ago
Button.php
20 hours ago
ConfirmationModal.php
20 hours ago
CourseFilter.php
20 hours ago
DateFilter.php
20 hours ago
DropdownFilter.php
20 hours ago
EmptyState.php
20 hours ago
FileUploader.php
20 hours ago
InputField.php
20 hours ago
Modal.php
20 hours ago
Nav.php
20 hours ago
Pagination.php
20 hours ago
Popover.php
20 hours ago
PreviewTrigger.php
20 hours ago
Progress.php
20 hours ago
SearchFilter.php
20 hours ago
Sorting.php
20 hours ago
StarRating.php
20 hours ago
StarRatingInput.php
20 hours ago
StatusSelect.php
20 hours ago
SvgIcon.php
20 hours ago
Table.php
20 hours ago
Tabs.php
20 hours ago
Tooltip.php
20 hours ago
WPEditor.php
20 hours ago
StarRatingInput.php
266 lines
| 1 | <?php |
| 2 | /** |
| 3 | * StarRatingInput Component Class. |
| 4 | * |
| 5 | * Renders an interactive star rating input using Alpine.js. |
| 6 | * |
| 7 | * @package Tutor\Components |
| 8 | * @author Themeum |
| 9 | * @link https://themeum.com |
| 10 | * @since 4.0.0 |
| 11 | */ |
| 12 | |
| 13 | namespace Tutor\Components; |
| 14 | |
| 15 | defined( 'ABSPATH' ) || exit; |
| 16 | |
| 17 | use TUTOR\Icon; |
| 18 | use Tutor\Components\Constants\Size; |
| 19 | |
| 20 | /** |
| 21 | * Class StarRatingInput |
| 22 | * |
| 23 | * Example Usage: |
| 24 | * ``` |
| 25 | * StarRatingInput::make() |
| 26 | * ->field_name('rating') |
| 27 | * ->current_rating(4.5) |
| 28 | * ->render(); |
| 29 | * ``` |
| 30 | * |
| 31 | * @since 4.0.0 |
| 32 | */ |
| 33 | class StarRatingInput extends BaseComponent { |
| 34 | |
| 35 | /** |
| 36 | * Form field name |
| 37 | * |
| 38 | * @since 4.0.0 |
| 39 | * |
| 40 | * @var string |
| 41 | */ |
| 42 | protected $field_name = 'rating'; |
| 43 | |
| 44 | /** |
| 45 | * Current rating value |
| 46 | * |
| 47 | * @since 4.0.0 |
| 48 | * |
| 49 | * @var float |
| 50 | */ |
| 51 | protected $current_rating = 0; |
| 52 | |
| 53 | /** |
| 54 | * On change callback function name or js snippet |
| 55 | * |
| 56 | * @since 4.0.0 |
| 57 | * |
| 58 | * @var string |
| 59 | */ |
| 60 | protected $on_change = ''; |
| 61 | |
| 62 | /** |
| 63 | * Alpine register function binding |
| 64 | * |
| 65 | * @since 4.0.0 |
| 66 | * |
| 67 | * @var string |
| 68 | */ |
| 69 | protected $register = ''; |
| 70 | |
| 71 | /** |
| 72 | * Icon size |
| 73 | * |
| 74 | * @var int |
| 75 | */ |
| 76 | protected $icon_size = Size::SIZE_20; |
| 77 | |
| 78 | /** |
| 79 | * View type (star|emoji) |
| 80 | * |
| 81 | * @var string |
| 82 | */ |
| 83 | protected $view = 'star'; |
| 84 | |
| 85 | /** |
| 86 | * Set field name |
| 87 | * |
| 88 | * @since 4.0.0 |
| 89 | * |
| 90 | * @param string $name field name. |
| 91 | * |
| 92 | * @return self |
| 93 | */ |
| 94 | public function field_name( string $name ): self { |
| 95 | $this->field_name = $name; |
| 96 | return $this; |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * Set current rating |
| 101 | * |
| 102 | * @since 4.0.0 |
| 103 | * |
| 104 | * @param float $rating rating. |
| 105 | * |
| 106 | * @return self |
| 107 | */ |
| 108 | public function current_rating( float $rating ): self { |
| 109 | $this->current_rating = $rating; |
| 110 | return $this; |
| 111 | } |
| 112 | |
| 113 | /** |
| 114 | * Set on change callback |
| 115 | * |
| 116 | * @since 4.0.0 |
| 117 | * |
| 118 | * @param string $callback callback. |
| 119 | * |
| 120 | * @return self |
| 121 | */ |
| 122 | public function on_change( string $callback ): self { |
| 123 | $this->on_change = $callback; |
| 124 | return $this; |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * Set register binding |
| 129 | * |
| 130 | * @since 4.0.0 |
| 131 | * |
| 132 | * @param string $register register. |
| 133 | * |
| 134 | * @return self |
| 135 | */ |
| 136 | public function register( string $register ): self { |
| 137 | $this->register = $register; |
| 138 | return $this; |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Set view type |
| 143 | * |
| 144 | * @since 4.0.0 |
| 145 | * |
| 146 | * @param string $view view type. |
| 147 | * |
| 148 | * @return self |
| 149 | */ |
| 150 | public function view( string $view ): self { |
| 151 | $this->view = $view; |
| 152 | return $this; |
| 153 | } |
| 154 | |
| 155 | /** |
| 156 | * Get component content |
| 157 | * |
| 158 | * @since 4.0.0 |
| 159 | * |
| 160 | * @return string |
| 161 | */ |
| 162 | public function get(): string { |
| 163 | $current_rating = $this->current_rating; |
| 164 | |
| 165 | $is_emoji = 'emoji' === $this->view; |
| 166 | $emoji_images = array( |
| 167 | 1 => 'poor.png', |
| 168 | 2 => 'fair.png', |
| 169 | 3 => 'okay.png', |
| 170 | 4 => 'good.png', |
| 171 | 5 => 'amazing.png', |
| 172 | ); |
| 173 | $emoji_url = tutor()->url . 'assets/images/emojis/'; |
| 174 | |
| 175 | $labels = array( |
| 176 | 1 => __( 'Poor', 'tutor' ), |
| 177 | 2 => __( 'Fair', 'tutor' ), |
| 178 | 3 => __( 'Okay', 'tutor' ), |
| 179 | 4 => __( 'Good', 'tutor' ), |
| 180 | 5 => __( 'Amazing', 'tutor' ), |
| 181 | ); |
| 182 | |
| 183 | $star_fill = SvgIcon::make()->name( Icon::STAR_FILL )->size( $is_emoji ? Size::SIZE_32 : Size::SIZE_24 )->ignore_kids()->get(); |
| 184 | $star_half = SvgIcon::make()->name( Icon::STAR_HALF )->size( $is_emoji ? Size::SIZE_32 : Size::SIZE_24 )->ignore_kids()->get(); |
| 185 | $star = SvgIcon::make()->name( Icon::STAR_LINE )->size( $is_emoji ? Size::SIZE_32 : Size::SIZE_24 )->ignore_kids()->get(); |
| 186 | |
| 187 | ob_start(); |
| 188 | ?> |
| 189 | <div |
| 190 | class="tutor-star-rating-container <?php echo $is_emoji ? 'is-emoji-view' : ''; ?>" |
| 191 | x-data="tutorStarRatingInput({ |
| 192 | initialRating: <?php echo esc_attr( $current_rating ); ?>, |
| 193 | fieldName: '<?php echo esc_attr( $this->field_name ); ?>' |
| 194 | })" |
| 195 | > |
| 196 | <input |
| 197 | type="hidden" |
| 198 | name="<?php echo esc_attr( $this->field_name ); ?>" |
| 199 | x-bind="register('<?php echo esc_attr( $this->field_name ); ?>' )" |
| 200 | > |
| 201 | |
| 202 | <?php if ( $is_emoji ) : ?> |
| 203 | <div class="tutor-flex tutor-items-center tutor-gap-4 tutor-justify-center"> |
| 204 | <?php |
| 205 | $rating_classes = array( |
| 206 | 1 => 'is-poor', |
| 207 | 2 => 'is-fair', |
| 208 | 3 => 'is-okay', |
| 209 | 4 => 'is-good', |
| 210 | 5 => 'is-amazing', |
| 211 | ); |
| 212 | ?> |
| 213 | <?php foreach ( $emoji_images as $i => $image ) : ?> |
| 214 | <button |
| 215 | type="button" |
| 216 | class="tutor-star-rating-emoji-btn <?php echo esc_attr( $rating_classes[ $i ] ); ?>" |
| 217 | :class="{'is-active': rating == <?php echo (int) $i; ?>}" |
| 218 | @click="setRating(<?php echo esc_attr( $i ); ?>, (rating) => setValue('<?php echo esc_attr( $this->field_name ); ?>', rating))" |
| 219 | > |
| 220 | <img src="<?php echo esc_url( $emoji_url . $image ); ?>" alt="<?php echo esc_attr( $labels[ $i ] ); ?>" class="tutor-rating-emoji-img" width="32" height="32"> |
| 221 | <span class="tutor-rating-label"> |
| 222 | <?php echo esc_html( $labels[ $i ] ); ?> |
| 223 | </span> |
| 224 | </button> |
| 225 | <?php endforeach; ?> |
| 226 | </div> |
| 227 | <?php endif; ?> |
| 228 | |
| 229 | <div class="tutor-flex tutor-items-center tutor-gap-2 tutor-justify-center" @mouseleave="hoverRating = 0"> |
| 230 | <?php for ( $i = 1; $i <= 5; $i++ ) : ?> |
| 231 | <button |
| 232 | type="button" |
| 233 | class="tutor-star-rating-icon-btn tutor-btn tutor-p-none tutor-min-h-0 tutor-bg-transparent" |
| 234 | @click="setRating(<?php echo esc_attr( $i ); ?>, (rating) => setValue('<?php echo esc_attr( $this->field_name ); ?>', rating))" |
| 235 | @mouseenter="hoverRating = <?php echo esc_attr( $i ); ?>" |
| 236 | > |
| 237 | <template x-if="effectiveRating >= <?php echo esc_attr( $i ); ?>"> |
| 238 | <span class="tutor-icon-exception4 tutor-flex"> |
| 239 | <?php echo $star_fill; // phpcs:ignore ?> |
| 240 | </span> |
| 241 | </template> |
| 242 | <template x-if="effectiveRating > <?php echo esc_attr( $i - 1 ); ?> && effectiveRating < <?php echo esc_attr( $i ); ?>"> |
| 243 | <span class="tutor-icon-exception4 tutor-flex"> |
| 244 | <?php echo $star_half; // phpcs:ignore ?> |
| 245 | </span> |
| 246 | </template> |
| 247 | <template x-if="effectiveRating <= <?php echo esc_attr( $i - 1 ); ?>"> |
| 248 | <span class="tutor-icon-exception4 tutor-flex"> |
| 249 | <?php echo $star; // phpcs:ignore ?> |
| 250 | </span> |
| 251 | </template> |
| 252 | </button> |
| 253 | <?php endfor; ?> |
| 254 | </div> |
| 255 | |
| 256 | <?php if ( ! $is_emoji ) : ?> |
| 257 | <span class="tutor-small tutor-font-medium" x-text="feedback"></span> |
| 258 | <?php endif; ?> |
| 259 | </div> |
| 260 | <?php |
| 261 | |
| 262 | $this->component_string = ob_get_clean(); |
| 263 | return $this->component_string; |
| 264 | } |
| 265 | } |
| 266 |