satupeta-main/app/(modules)/(landing)/components/feedback/_components/emoji-rating.tsx

111 lines
2.8 KiB
TypeScript
Raw Normal View History

2026-01-27 02:31:12 +00:00
"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>
);
}