91 lines
2.1 KiB
TypeScript
91 lines
2.1 KiB
TypeScript
import React from 'react';
|
|
import { Star } from 'lucide-react';
|
|
|
|
interface RatingStarsProps {
|
|
rating: number;
|
|
maxRating?: number;
|
|
size?: 'sm' | 'md' | 'lg';
|
|
showNumber?: boolean;
|
|
interactive?: boolean;
|
|
onRatingChange?: (rating: number) => void;
|
|
}
|
|
|
|
const RatingStars: React.FC<RatingStarsProps> = ({
|
|
rating,
|
|
maxRating = 5,
|
|
size = 'md',
|
|
showNumber = false,
|
|
interactive = false,
|
|
onRatingChange,
|
|
}) => {
|
|
const [hoveredRating, setHoveredRating] =
|
|
React.useState<number | null>(null);
|
|
|
|
const sizeClasses = {
|
|
sm: 'w-4 h-4',
|
|
md: 'w-5 h-5',
|
|
lg: 'w-6 h-6',
|
|
};
|
|
|
|
const handleClick = (value: number) => {
|
|
if (interactive && onRatingChange) {
|
|
onRatingChange(value);
|
|
}
|
|
};
|
|
|
|
const handleMouseEnter = (value: number) => {
|
|
if (interactive) {
|
|
setHoveredRating(value);
|
|
}
|
|
};
|
|
|
|
const handleMouseLeave = () => {
|
|
if (interactive) {
|
|
setHoveredRating(null);
|
|
}
|
|
};
|
|
|
|
const displayRating = hoveredRating ?? rating;
|
|
|
|
return (
|
|
<div className="flex items-center gap-1">
|
|
{Array.from({ length: maxRating }, (_, index) => {
|
|
const starValue = index + 1;
|
|
const isFilled = starValue <= displayRating;
|
|
|
|
return (
|
|
<button
|
|
key={index}
|
|
type="button"
|
|
onClick={() => handleClick(starValue)}
|
|
onMouseEnter={() => handleMouseEnter(starValue)}
|
|
onMouseLeave={handleMouseLeave}
|
|
disabled={!interactive}
|
|
className={`${
|
|
interactive
|
|
? 'cursor-pointer hover:scale-110 transition-transform'
|
|
: 'cursor-default'
|
|
}`}
|
|
aria-label={`${starValue} star${starValue > 1 ? 's' : ''}`}
|
|
>
|
|
<Star
|
|
className={`${sizeClasses[size]} ${
|
|
isFilled
|
|
? 'text-[#d4af37] fill-[#d4af37]'
|
|
: 'text-gray-500'
|
|
}`}
|
|
/>
|
|
</button>
|
|
);
|
|
})}
|
|
{showNumber && (
|
|
<span className="ml-2 text-xs sm:text-sm font-semibold text-white">
|
|
{rating.toFixed(1)}
|
|
</span>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default RatingStars;
|