nextav/src/components/star-rating.tsx

66 lines
1.5 KiB
TypeScript

'use client';
import { Star } from 'lucide-react';
import { cn } from '@/lib/utils';
interface StarRatingProps {
rating: number;
count?: number;
size?: 'sm' | 'md' | 'lg';
showCount?: boolean;
interactive?: boolean;
onRate?: (rating: number) => void;
className?: string;
}
export function StarRating({
rating,
count = 0,
size = 'md',
showCount = false,
interactive = false,
onRate,
className
}: StarRatingProps) {
const sizeClasses = {
sm: 'h-3 w-3',
md: 'h-4 w-4',
lg: 'h-5 w-5'
};
const handleRate = (newRating: number) => {
if (interactive && onRate) {
onRate(newRating);
}
};
return (
<div className={cn("flex items-center gap-1", className)}>
{[1, 2, 3, 4, 5].map((star) => (
<button
key={star}
type="button"
disabled={!interactive}
onClick={() => handleRate(star)}
className={cn(
"transition-colors",
interactive ? "cursor-pointer hover:text-yellow-400" : "cursor-default",
star <= Math.round(rating) ? "text-yellow-400" : "text-gray-300"
)}
>
<Star
className={cn(
sizeClasses[size],
star <= Math.round(rating) ? "fill-yellow-400" : "fill-transparent"
)}
/>
</button>
))}
{showCount && count > 0 && (
<span className="text-xs text-muted-foreground ml-1">
({count})
</span>
)}
</div>
);
}