Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 5x 17x 11x 11x 12x 11x 12x 12x 12x 12x 12x 11x 55x 35x 11x 55x 44x 33x 22x 11x 55x 55x | 'use client';
import React from 'react';
import { Star, PenLine } from 'lucide-react';
import { Review } from '../types';
interface ReviewSummaryProps {
reviews: Review[];
onWriteReview?: () => void;
}
export const ReviewSummary: React.FC<ReviewSummaryProps> = ({ reviews, onWriteReview }) => {
// Calculate statistics from approved reviews only
const approvedReviews = reviews.filter(r => r.status === 'approved');
const totalReviews = approvedReviews.length;
// Calculate average rating
const averageRating = totalReviews > 0
? approvedReviews.reduce((sum, r) => sum + r.rating, 0) / totalReviews
: 0;
// Count reviews by star rating
const starCounts = {
5: approvedReviews.filter(r => r.rating === 5).length,
4: approvedReviews.filter(r => r.rating === 4).length,
3: approvedReviews.filter(r => r.rating === 3).length,
2: approvedReviews.filter(r => r.rating === 2).length,
1: approvedReviews.filter(r => r.rating === 1).length,
};
// Calculate percentages for bar widths
const getBarWidth = (count: number) => {
if (totalReviews === 0) return 0;
return (count / totalReviews) * 100;
};
// Get star color based on rating level
const getBarColor = (stars: number) => {
if (stars === 5) return 'bg-yellow-500';
if (stars === 4) return 'bg-yellow-500';
if (stars === 3) return 'bg-yellow-500';
return 'bg-gray-300';
};
return (
<div className="space-y-6">
{/* Header with button */}
<div className="flex items-center justify-between gap-4">
<h3 className="text-xl font-bold text-black">Arvostelujen yhteenveto</h3>
<button
onClick={onWriteReview}
className="bg-black text-white px-6 py-3 rounded-full font-bold text-sm inline-flex items-center gap-2 hover:bg-gray-800 transition-all hover:scale-105 shadow-lg"
>
<PenLine size={16} strokeWidth={2.5} />
Kirjoita arvostelu
</button>
</div>
{/* Main content */}
<div className="flex flex-col md:flex-row gap-8 md:gap-16 items-start">
{/* Left side: Average rating */}
<div className="flex flex-col items-start">
<div className="text-6xl font-black tracking-tight text-black mb-2">
{averageRating.toFixed(1).replace('.', ',')}
</div>
{/* Stars */}
<div className="flex gap-0.5 mb-3">
{[...Array(5)].map((_, i) => (
<Star
key={i}
size={20}
className={i < Math.round(averageRating) ? 'fill-yellow-500 text-yellow-500' : 'fill-gray-300 text-gray-300'}
/>
))}
</div>
<p className="text-sm text-gray-600 font-medium">
{totalReviews} arvostelua
</p>
</div>
{/* Right side: Distribution bars */}
<div className="flex-1 w-full space-y-3">
{[5, 4, 3, 2, 1].map((stars) => (
<div key={stars} className="flex items-center gap-4">
<span className="text-sm font-medium text-gray-600 w-2">{stars}</span>
{/* Bar track */}
<div className="flex-1 h-2 bg-gray-200 rounded-full overflow-hidden">
{/* Bar fill */}
<div
className={`h-full rounded-full transition-all duration-500 ${getBarColor(stars)}`}
style={{ width: `${getBarWidth(starCounts[stars as keyof typeof starCounts])}%` }}
/>
</div>
{/* Count */}
<span className="text-sm text-gray-500 w-6 text-right">
{starCounts[stars as keyof typeof starCounts]}
</span>
</div>
))}
</div>
</div>
</div>
);
};
|