"use client" import { useState } from "react" import { useAuth } from "@/contexts/auth-context" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Textarea } from "@/components/ui/textarea" import { Badge } from "@/components/ui/badge" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Alert, AlertDescription } from "@/components/ui/alert" import { Separator } from "@/components/ui/separator" import { Star, MessageSquare, ThumbsUp, ThumbsDown, Edit, Trash2, MoreHorizontal } from "lucide-react" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog" interface Review { id: string userId: string userName: string userAvatar?: string userDepartment: string rating: number comment: string createdAt: string updatedAt?: string helpful: number notHelpful: number userHelpfulVotes: string[] // user IDs who voted helpful userNotHelpfulVotes: string[] // user IDs who voted not helpful } interface ReviewSystemProps { appId: string appName: string currentRating: number onRatingUpdate: (newRating: number, reviewCount: number) => void } export function ReviewSystem({ appId, appName, currentRating, onRatingUpdate }: ReviewSystemProps) { const { user, updateAppRating } = useAuth() // Load reviews from localStorage const [reviews, setReviews] = useState(() => { if (typeof window !== "undefined") { const saved = localStorage.getItem(`reviews_${appId}`) return saved ? JSON.parse(saved) : [] } return [] }) const [showReviewForm, setShowReviewForm] = useState(false) const [newRating, setNewRating] = useState(5) const [newComment, setNewComment] = useState("") const [isSubmitting, setIsSubmitting] = useState(false) const [editingReview, setEditingReview] = useState(null) const [sortBy, setSortBy] = useState<"newest" | "oldest" | "helpful">("newest") const userReview = reviews.find((review) => review.userId === user?.id) const canReview = user && !userReview // Save reviews to localStorage and update app rating const saveReviews = (updatedReviews: Review[]) => { if (typeof window !== "undefined") { localStorage.setItem(`reviews_${appId}`, JSON.stringify(updatedReviews)) } setReviews(updatedReviews) // Calculate new average rating and update in context if (updatedReviews.length > 0) { const avgRating = updatedReviews.reduce((sum, r) => sum + r.rating, 0) / updatedReviews.length const newAvgRating = Number(avgRating.toFixed(1)) updateAppRating(appId, newAvgRating) onRatingUpdate(newAvgRating, updatedReviews.length) } else { updateAppRating(appId, 0) onRatingUpdate(0, 0) } } const handleSubmitReview = async () => { if (!user || !newComment.trim()) return setIsSubmitting(true) const review: Review = { id: `r${Date.now()}`, userId: user.id, userName: user.name, userAvatar: user.avatar, userDepartment: user.department, rating: newRating, comment: newComment.trim(), createdAt: new Date().toISOString(), helpful: 0, notHelpful: 0, userHelpfulVotes: [], userNotHelpfulVotes: [], } const updatedReviews = [...reviews, review] saveReviews(updatedReviews) setNewComment("") setNewRating(5) setShowReviewForm(false) setIsSubmitting(false) } const handleEditReview = async (reviewId: string) => { if (!user || !newComment.trim()) return setIsSubmitting(true) const updatedReviews = reviews.map((review) => review.id === reviewId ? { ...review, rating: newRating, comment: newComment.trim(), updatedAt: new Date().toISOString(), } : review, ) saveReviews(updatedReviews) setEditingReview(null) setNewComment("") setNewRating(5) setIsSubmitting(false) } const handleDeleteReview = async (reviewId: string) => { const updatedReviews = reviews.filter((review) => review.id !== reviewId) saveReviews(updatedReviews) } const handleHelpfulVote = (reviewId: string, isHelpful: boolean) => { if (!user) return const updatedReviews = reviews.map((review) => { if (review.id !== reviewId) return review const helpfulVotes = [...review.userHelpfulVotes] const notHelpfulVotes = [...review.userNotHelpfulVotes] if (isHelpful) { if (helpfulVotes.includes(user.id)) { // Remove helpful vote const index = helpfulVotes.indexOf(user.id) helpfulVotes.splice(index, 1) } else { // Add helpful vote and remove not helpful if exists helpfulVotes.push(user.id) const notHelpfulIndex = notHelpfulVotes.indexOf(user.id) if (notHelpfulIndex > -1) { notHelpfulVotes.splice(notHelpfulIndex, 1) } } } else { if (notHelpfulVotes.includes(user.id)) { // Remove not helpful vote const index = notHelpfulVotes.indexOf(user.id) notHelpfulVotes.splice(index, 1) } else { // Add not helpful vote and remove helpful if exists notHelpfulVotes.push(user.id) const helpfulIndex = helpfulVotes.indexOf(user.id) if (helpfulIndex > -1) { helpfulVotes.splice(helpfulIndex, 1) } } } return { ...review, helpful: helpfulVotes.length, notHelpful: notHelpfulVotes.length, userHelpfulVotes: helpfulVotes, userNotHelpfulVotes: notHelpfulVotes, } }) saveReviews(updatedReviews) } const startEdit = (review: Review) => { setEditingReview(review.id) setNewRating(review.rating) setNewComment(review.comment) setShowReviewForm(true) } const cancelEdit = () => { setEditingReview(null) setNewComment("") setNewRating(5) setShowReviewForm(false) } const sortedReviews = [...reviews].sort((a, b) => { switch (sortBy) { case "oldest": return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() case "helpful": return b.helpful - a.helpful case "newest": default: return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() } }) const getInitials = (name: string) => { return name.split("").slice(0, 2).join("").toUpperCase() } const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString("zh-TW", { year: "numeric", month: "long", day: "numeric", hour: "2-digit", minute: "2-digit", }) } const renderStars = (rating: number, interactive = false, onRate?: (rating: number) => void) => { return (
{[1, 2, 3, 4, 5].map((star) => ( interactive && onRate && onRate(star)} /> ))}
) } return (
{/* Review Summary */} 用戶評價 {reviews.length > 0 ? (
{renderStars(Math.round(currentRating))} {currentRating} ({reviews.length} 則評價)
) : ( "尚無評價,成為第一個評價的用戶!" )}
{/* Rating Distribution */} {reviews.length > 0 && (
{[5, 4, 3, 2, 1].map((rating) => { const count = reviews.filter((r) => r.rating === rating).length const percentage = (count / reviews.length) * 100 return (
{rating}
{count}
) })}
)} {/* Add Review Button */} {canReview && ( )} {userReview && ( 您已經評價過此應用。您可以編輯或刪除您的評價。 )} {/* Review Form */} {editingReview ? "編輯評價" : "撰寫評價"} 分享您對 {appName} 的使用體驗
{renderStars(newRating, true, setNewRating)}