Add rating scale component
This commit is contained in:
parent
1183e0c016
commit
e86c36248c
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
"postcss-import": {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
|
||||
type RGB = [number, number, number];
|
||||
const red: RGB = [221, 103, 81]; // red-600
|
||||
const yellow: RGB = [250, 200, 82]; // yellow-500
|
||||
const lightGreen: RGB = [120, 222, 163]; // green-500
|
||||
const darkGreen: RGB = [91, 183, 130]; // green-600
|
||||
|
||||
const props = defineProps<{
|
||||
rating: number;
|
||||
}>();
|
||||
|
||||
const weight = computed(() => {
|
||||
return props.rating % 1;
|
||||
});
|
||||
|
||||
const scale = computed(() => {
|
||||
return Math.floor(props.rating);
|
||||
});
|
||||
|
||||
const colors = computed(() => {
|
||||
switch (scale.value) {
|
||||
case 1:
|
||||
return [red, yellow];
|
||||
case 2:
|
||||
return [yellow, lightGreen];
|
||||
case 3:
|
||||
default:
|
||||
return [lightGreen, darkGreen];
|
||||
}
|
||||
});
|
||||
|
||||
const blendColorValue = (v1: number, v2: number, weight: number) => {
|
||||
return v1 * weight + v2 * (1 - weight);
|
||||
};
|
||||
|
||||
const blendColors = (c1: RGB, c2: RGB, weight: number): RGB => {
|
||||
const [r1, g1, b1] = c1;
|
||||
const [r2, g2, b2] = c2;
|
||||
return [
|
||||
blendColorValue(r1, r2, weight),
|
||||
blendColorValue(g1, g2, weight),
|
||||
blendColorValue(b1, b2, weight),
|
||||
];
|
||||
};
|
||||
|
||||
const getRGBString = ([r, g, b]: RGB) => {
|
||||
return `rgb(${Math.floor(r)}, ${Math.floor(g)}, ${Math.floor(b)})`;
|
||||
};
|
||||
|
||||
const getRGBStyle = (c1: RGB, c2: RGB, weight: number) => {
|
||||
return getRGBString(blendColors(c1, c2, weight));
|
||||
};
|
||||
|
||||
const getLeftPosition = (rating:number, weight: number) => {
|
||||
const percent = (rating - 1) * 33 + weight * 25;
|
||||
return `${Math.floor(percent)}%`;
|
||||
};
|
||||
|
||||
const style = {
|
||||
backgroundColor: getRGBStyle(colors.value[0], colors.value[1], weight.value),
|
||||
left: getLeftPosition(scale.value, weight.value),
|
||||
};
|
||||
|
||||
console.log(props);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h3>{{ props.rating }} - {{ weight }} = {{style}}</h3>
|
||||
<div class="gradient-with-circle pt-3 relative">
|
||||
<!-- <div -->
|
||||
<!-- class="circle" -->
|
||||
<!-- :style="{ -->
|
||||
<!-- backgroundColor: getRGBStyle(yellow, red, 0.5), -->
|
||||
<!-- left: getLeftPosition(0.5), -->
|
||||
<!-- }" -->
|
||||
<!-- ></div> -->
|
||||
<!-- <div -->
|
||||
<!-- class="circle" -->
|
||||
<!-- :style="{ -->
|
||||
<!-- backgroundColor: getRGBStyle(yellow, red, 0.25), -->
|
||||
<!-- left: getLeftPosition(0.25), -->
|
||||
<!-- }" -->
|
||||
<!-- ></div> -->
|
||||
<div class="circle" :style="style"></div>
|
||||
<div class="h-2 gradient"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.circle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 32px;
|
||||
position: absolute;
|
||||
transform: translateX(-50%);
|
||||
top: 0;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.circle:before {
|
||||
content: "";
|
||||
background-color: white;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.gradient {
|
||||
background-color: theme(colors.yellow.400);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
theme(colors.red.600) 0%,
|
||||
theme(colors.yellow.500) 33%,
|
||||
theme(colors.green.500) 66%,
|
||||
theme(colors.green.600) 100%
|
||||
);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -7,6 +7,7 @@ import ItDropdown from "@/components/ui/ItDropdown.vue";
|
|||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import ItRadioGroup from "@/components/ui/ItRadioGroup.vue";
|
||||
import ItTextarea from "@/components/ui/ItTextarea.vue";
|
||||
import RatingScale from "@/components/ui/RatingScale.vue";
|
||||
import logger from "loglevel";
|
||||
import { reactive, ref } from "vue";
|
||||
|
||||
|
|
@ -424,6 +425,13 @@ function log(data: any) {
|
|||
:label="satisfactionText"
|
||||
:items="satisfactionValues"
|
||||
/>
|
||||
<div>
|
||||
<RatingScale :rating="1" />
|
||||
<RatingScale :rating="1.3" />
|
||||
<RatingScale :rating="2.5" />
|
||||
<RatingScale :rating="3.9" />
|
||||
<RatingScale :rating="4" />
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue