update
This commit is contained in:
90
Frontend/src/features/rooms/components/RatingStars.tsx
Normal file
90
Frontend/src/features/rooms/components/RatingStars.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user