105 lines
2.6 KiB
Vue
105 lines
2.6 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
import { round } from "../utils/math";
|
|
|
|
const props = defineProps({
|
|
id: { type: [String, Number] },
|
|
showText: { type: Boolean, default: true },
|
|
disabled: { type: Boolean, default: false },
|
|
size: { type: String as () => "xs" | "sm" | "md" | "lg", default: "md" },
|
|
});
|
|
|
|
const model = defineModel<number>();
|
|
|
|
function onUpdateRating(change) {
|
|
model.value = change.target.value;
|
|
}
|
|
|
|
const rounded = computed(() => {
|
|
if (model.value === undefined || model.value === null) {
|
|
return 0;
|
|
} else {
|
|
return Math.round(model.value);
|
|
}
|
|
});
|
|
|
|
const text = computed(() => {
|
|
if (model.value === undefined || model.value === null) {
|
|
return "0";
|
|
}
|
|
return `${round(model.value, 1)}`;
|
|
});
|
|
|
|
const ratingClass = computed(() => {
|
|
const ratingSize = {
|
|
xs: "rating-xs",
|
|
sm: "rating-sm",
|
|
md: "rating-md",
|
|
lg: "rating-lg",
|
|
};
|
|
return ratingSize[props.size];
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-row items-center">
|
|
<label class="flex-0 align-bottom flex-grow-0 text-gray-500" v-if="showText" for="rating=input">{{ text }}</label>
|
|
<div id="rating-input" :class="'rating align-bottom flex-0 flex-grow-0 ' + ratingClass">
|
|
<input
|
|
type="radio"
|
|
:disabled="props.disabled"
|
|
:name="`rating-${props.id}`"
|
|
value="0"
|
|
class="rating-hidden"
|
|
:checked="rounded == 0"
|
|
@change="onUpdateRating"
|
|
/>
|
|
<input
|
|
type="radio"
|
|
:disabled="props.disabled"
|
|
:name="`rating-${props.id}`"
|
|
value="1"
|
|
class="bg-amber-400 mask mask-star"
|
|
:checked="rounded == 1"
|
|
@change="onUpdateRating"
|
|
/>
|
|
<input
|
|
type="radio"
|
|
:disabled="props.disabled"
|
|
:name="`rating-${props.id}`"
|
|
value="2"
|
|
class="bg-amber-400 mask mask-star"
|
|
:checked="rounded == 2"
|
|
@change="onUpdateRating"
|
|
/>
|
|
<input
|
|
type="radio"
|
|
:disabled="props.disabled"
|
|
:name="`rating-${props.id}`"
|
|
value="3"
|
|
class="bg-amber-400 mask mask-star"
|
|
:checked="rounded == 3"
|
|
@change="onUpdateRating"
|
|
/>
|
|
<input
|
|
type="radio"
|
|
:disabled="props.disabled"
|
|
:name="`rating-${props.id}`"
|
|
value="4"
|
|
class="bg-amber-400 mask mask-star"
|
|
:checked="rounded == 4"
|
|
@change="onUpdateRating"
|
|
/>
|
|
<input
|
|
type="radio"
|
|
:disabled="props.disabled"
|
|
:name="`rating-${props.id}`"
|
|
value="5"
|
|
class="bg-amber-400 mask mask-star"
|
|
:checked="rounded == 5"
|
|
@change="onUpdateRating"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|