Constants
22 hours ago
Accordion.php
22 hours ago
Alert.php
22 hours ago
AttachmentCard.php
22 hours ago
Avatar.php
22 hours ago
Badge.php
22 hours ago
BaseComponent.php
22 hours ago
Button.php
22 hours ago
ConfirmationModal.php
22 hours ago
CourseFilter.php
22 hours ago
DateFilter.php
22 hours ago
DropdownFilter.php
22 hours ago
EmptyState.php
22 hours ago
FileUploader.php
22 hours ago
InputField.php
22 hours ago
Modal.php
22 hours ago
Nav.php
22 hours ago
Pagination.php
22 hours ago
Popover.php
22 hours ago
PreviewTrigger.php
22 hours ago
Progress.php
22 hours ago
SearchFilter.php
22 hours ago
Sorting.php
22 hours ago
StarRating.php
22 hours ago
StarRatingInput.php
22 hours ago
StatusSelect.php
22 hours ago
SvgIcon.php
22 hours ago
Table.php
22 hours ago
Tabs.php
22 hours ago
Tooltip.php
22 hours ago
WPEditor.php
22 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 |