Add Workout Library feature with browse, create, and favorites
This commit is contained in:
105
src/components/workout/StarRating.vue
Normal file
105
src/components/workout/StarRating.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<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 } 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>
|
||||
Reference in New Issue
Block a user