<template>
  <div class="star-rating" :class="[`size-${size}`, { readonly }]">
    <button
      v-for="star in 5"
      :key="star"
      type="button"
      class="star-btn"
      :class="{ filled: star <= displayRating, hovered: star <= hoverRating }"
      @click="!readonly && selectRating(star)"
      @mouseenter="!readonly && (hoverRating = star)"
      @mouseleave="hoverRating = 0"
      :disabled="readonly"
    >
      <svg viewBox="0 0 24 24" fill="none">
        <path
          d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"
          :fill="star <= displayRating || star <= hoverRating ? 'currentColor' : 'none'"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        />
      </svg>
    </button>
  </div>
</template>

<script setup>
import { ref, computed, defineProps, defineEmits } from 'vue'

const props = defineProps({
  rating: {
    type: Number,
    default: 0
  },
  readonly: {
    type: Boolean,
    default: false
  },
  size: {
    type: String,
    default: 'medium',
    validator: (v) => ['small', 'medium', 'large'].includes(v)
  }
})

const emit = defineEmits(['update:rating', 'rate'])

const hoverRating = ref(0)

const displayRating = computed(() => Math.round(props.rating))

function selectRating(star) {
  emit('update:rating', star)
  emit('rate', star)
}
</script>

<style scoped>
.star-rating {
  display: inline-flex;
  gap: 2px;
}

.star-btn {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--color-border);
  transition: all var(--transition-base);
}

.star-btn:disabled {
  cursor: default;
}

.star-btn.filled,
.star-btn.hovered {
  color: #f5a623;
}

.star-btn:not(:disabled):hover {
  transform: scale(1.1);
}

.readonly .star-btn {
  cursor: default;
}

.size-small .star-btn svg {
  width: 14px;
  height: 14px;
}

.size-medium .star-btn svg {
  width: 20px;
  height: 20px;
}

.size-large .star-btn svg {
  width: 28px;
  height: 28px;
}
</style>
