Initial: pi-skill — 68 skills, 43 extensions, 11 themes for Pi
This commit is contained in:
122
skills/scripts/templates/src/components/review/ReviewList.tsx
Normal file
122
skills/scripts/templates/src/components/review/ReviewList.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import StarRating from './StarRating';
|
||||
|
||||
interface Review {
|
||||
id: string;
|
||||
rating: number;
|
||||
title?: string;
|
||||
comment: string;
|
||||
user: { name: string; avatar_url?: string };
|
||||
created_at: string;
|
||||
images?: string[];
|
||||
}
|
||||
|
||||
interface ReviewListProps {
|
||||
reviews: Review[];
|
||||
productId?: string;
|
||||
onLoadMore?: () => void;
|
||||
hasMore?: boolean;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
export default function ReviewList({
|
||||
reviews,
|
||||
productId,
|
||||
onLoadMore,
|
||||
hasMore = false,
|
||||
isLoading = false
|
||||
}: ReviewListProps) {
|
||||
if (!reviews?.length) {
|
||||
return (
|
||||
<div className="text-center py-12">
|
||||
<div className="w-16 h-16 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="font-medium text-gray-900 mb-1">ยังไม่มีรีวิว</h3>
|
||||
<p className="text-gray-500 text-sm">เป็นคนแรกที่รีวิวสินค้านี้</p>
|
||||
<a
|
||||
href={`#write-review${productId ? `?productId=${productId}` : ''}`}
|
||||
className="mt-4 inline-block text-blue-600 hover:text-blue-700 text-sm font-medium"
|
||||
>
|
||||
เขียนรีวิว
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{reviews.map(review => (
|
||||
<div key={review.id} className="border-b pb-6 last:border-b-0">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-gray-200 rounded-full flex items-center justify-center overflow-hidden">
|
||||
{review.user.avatar_url ? (
|
||||
<img
|
||||
src={review.user.avatar_url}
|
||||
alt={review.user.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<span className="text-gray-500 font-medium">
|
||||
{review.user.name.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-medium text-gray-900">{review.user.name}</p>
|
||||
<StarRating rating={review.rating} size={14} />
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-sm text-gray-500">
|
||||
{new Date(review.created_at).toLocaleDateString('th-TH', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{review.title && (
|
||||
<h4 className="font-medium text-gray-900 mb-1">{review.title}</h4>
|
||||
)}
|
||||
|
||||
<p className="text-gray-600 leading-relaxed">{review.comment}</p>
|
||||
|
||||
{review.images && review.images.length > 0 && (
|
||||
<div className="flex gap-2 mt-4 overflow-x-auto pb-2">
|
||||
{review.images.map((img, i) => (
|
||||
<a
|
||||
key={i}
|
||||
href={img}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex-shrink-0"
|
||||
>
|
||||
<img
|
||||
src={img}
|
||||
alt={`รูปรีวิว ${i + 1}`}
|
||||
className="w-20 h-20 object-cover rounded-lg hover:opacity-80 transition-opacity"
|
||||
/>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
{hasMore && (
|
||||
<div className="text-center pt-4">
|
||||
<button
|
||||
onClick={onLoadMore}
|
||||
disabled={isLoading}
|
||||
className="px-6 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
{isLoading ? 'กำลังโหลด...' : 'ดูรีวิวเพิ่มเติม'}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user