star_rating_controller.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { Controller } from '@hotwired/stimulus';
  2. export default class extends Controller {
  3. static values = {
  4. value: { type: Number, default: 0 },
  5. max: { type: Number, default: 5 },
  6. step: { type: Number, default: 1 },
  7. disabled: { type: Boolean, default: false },
  8. size: { type: String, default: 'md' }
  9. };
  10. connect() {
  11. this.updateDisplay();
  12. if (!this.disabledValue) {
  13. this.element.style.cursor = 'pointer';
  14. }
  15. }
  16. valueValueChanged() {
  17. this.updateDisplay();
  18. }
  19. updateDisplay() {
  20. const stars = this.element.querySelectorAll('.star');
  21. const value = this.valueValue;
  22. const max = this.maxValue;
  23. stars.forEach((star, index) => {
  24. const starValue = index + 1;
  25. // Pour les étapes de 0.5
  26. if (this.stepValue === 0.5) {
  27. if (value >= starValue) {
  28. star.classList.remove('fa-regular', 'fa-star-half-stroke');
  29. star.classList.add('fa-solid');
  30. } else if (value >= starValue - 0.5) {
  31. star.classList.remove('fa-solid', 'fa-regular');
  32. star.classList.add('fa-star-half-stroke');
  33. } else {
  34. star.classList.remove('fa-solid', 'fa-star-half-stroke');
  35. star.classList.add('fa-regular');
  36. }
  37. } else {
  38. // Pour les étapes de 1
  39. if (value >= starValue) {
  40. star.classList.remove('fa-regular');
  41. star.classList.add('fa-solid');
  42. } else {
  43. star.classList.remove('fa-solid');
  44. star.classList.add('fa-regular');
  45. }
  46. }
  47. });
  48. }
  49. handleClick(event) {
  50. if (this.disabledValue) return;
  51. const clickedStar = event.target.closest('.star');
  52. if (!clickedStar) return;
  53. const stars = Array.from(this.element.querySelectorAll('.star'));
  54. const clickedIndex = stars.indexOf(clickedStar);
  55. const starValue = clickedIndex + 1;
  56. // Gérer les demi-étoiles pour step=0.5
  57. if (this.stepValue === 0.5) {
  58. const rect = clickedStar.getBoundingClientRect();
  59. const clickX = event.clientX - rect.left;
  60. const starWidth = rect.width;
  61. // Si on clique sur la moitié gauche, on met une demi-étoile
  62. if (clickX < starWidth / 2 && starValue <= this.maxValue) {
  63. this.valueValue = starValue - 0.5;
  64. } else {
  65. this.valueValue = starValue;
  66. }
  67. } else {
  68. this.valueValue = starValue;
  69. }
  70. // Dispatch un événement pour notifier du changement
  71. this.element.dispatchEvent(new CustomEvent('change', {
  72. detail: { value: this.valueValue }
  73. }));
  74. }
  75. get sizeClass() {
  76. const sizes = {
  77. 'xs': 'fa-xs',
  78. 'sm': 'fa-sm',
  79. 'md': '',
  80. 'lg': 'fa-lg',
  81. 'xl': 'fa-xl',
  82. '2x': 'fa-2x',
  83. '3x': 'fa-3x'
  84. };
  85. return sizes[this.sizeValue] || '';
  86. }
  87. }