111 lines
2.8 KiB
TypeScript
Executable File
111 lines
2.8 KiB
TypeScript
Executable File
"use client";
|
|
|
|
import { Label } from "@/shared/components/ui/label"; // atau pakai <label> native
|
|
import { RadioGroup, RadioGroupItem } from "@radix-ui/react-radio-group";
|
|
import Image from "next/image";
|
|
|
|
type RatingOptions = {
|
|
value: 1 | 2 | 3 | 4 | 5;
|
|
label: string;
|
|
src: string;
|
|
};
|
|
|
|
const ratingOptions: RatingOptions[] = [
|
|
{
|
|
value: 1,
|
|
label: "Sangat Tidak Puas",
|
|
src: "/icons/emoji-0.svg",
|
|
},
|
|
{
|
|
value: 2,
|
|
label: "Tidak puas",
|
|
src: "/icons/emoji-1.svg",
|
|
},
|
|
{
|
|
value: 3,
|
|
label: "Biasa saja",
|
|
src: "/icons/emoji-2.svg",
|
|
},
|
|
{
|
|
value: 4,
|
|
label: "Puas",
|
|
src: "/icons/emoji-3.svg",
|
|
},
|
|
{
|
|
value: 5,
|
|
label: "Sangat Puas",
|
|
src: "/icons/emoji-4.svg",
|
|
},
|
|
];
|
|
|
|
export default function EmojiRatingFeedback({
|
|
value,
|
|
onChange,
|
|
size = 44,
|
|
name = "score",
|
|
}: {
|
|
value: number;
|
|
onChange: (v: number) => void;
|
|
showLabel?: boolean;
|
|
size?: number;
|
|
name?: string;
|
|
}) {
|
|
return (
|
|
<div className="w-full">
|
|
<RadioGroup
|
|
name={name}
|
|
value={value != null ? String(value) : ""} // selalu controlled
|
|
onValueChange={(v) => onChange(Number(v))}
|
|
className="grid grid-cols-5"
|
|
aria-label="Rating kepuasan"
|
|
>
|
|
{ratingOptions.map((option) => {
|
|
const isActive = (value ?? 0) === option.value;
|
|
const id = `score-${option.value}`;
|
|
return (
|
|
<div
|
|
key={option.value}
|
|
className="group grid place-items-center gap-1"
|
|
>
|
|
<RadioGroupItem
|
|
id={id}
|
|
value={String(option.value)}
|
|
className="sr-only"
|
|
/>
|
|
|
|
<Label
|
|
htmlFor={id}
|
|
className={[
|
|
"rounded-full p-1 transition transform cursor-pointer outline-none",
|
|
isActive
|
|
? "ring-2 ring-offset-2 ring-orange-500 scale-110"
|
|
: "opacity-80 hover:opacity-100 hover:scale-105 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-orange-500",
|
|
].join(" ")}
|
|
>
|
|
<Image
|
|
src={option.src}
|
|
alt={option.label}
|
|
width={size}
|
|
height={size}
|
|
draggable={false}
|
|
/>
|
|
</Label>
|
|
|
|
{/* Label kecil: muncul saat hover atau saat terpilih */}
|
|
<span
|
|
className={[
|
|
"text-xs text-gray-900 leading-3 text-center mt-2 opacity-0 transition-opacity",
|
|
"group-hover:opacity-100",
|
|
isActive ? "opacity-100" : "",
|
|
].join(" ")}
|
|
>
|
|
{option.label}
|
|
</span>
|
|
</div>
|
|
);
|
|
})}
|
|
</RadioGroup>
|
|
</div>
|
|
);
|
|
}
|