Approve tool use
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useAuth } from '@/contexts/AuthContext';
|
||||
import { reviewService, ReviewStats, type Review, type ReviewReply } from '@/services/reviewService';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import {
|
||||
Star,
|
||||
ThumbsUp,
|
||||
@@ -23,114 +25,50 @@ import { Progress } from '@/components/ui/progress';
|
||||
import { ReviewReplyDialog } from '@/components/dashboard/ReviewReplyDialog';
|
||||
import { ReviewPhotoUpload } from '@/components/dashboard/ReviewPhotoUpload';
|
||||
|
||||
interface ReviewReply {
|
||||
id: string;
|
||||
authorId: string;
|
||||
authorName: string;
|
||||
authorAvatar: string;
|
||||
content: string;
|
||||
createdAt: string;
|
||||
images?: string[];
|
||||
}
|
||||
|
||||
interface Review {
|
||||
id: string;
|
||||
itemId: string;
|
||||
userId: string;
|
||||
userName: string;
|
||||
userAvatar: string;
|
||||
rating: number;
|
||||
comment: string;
|
||||
images: string[];
|
||||
createdAt: string;
|
||||
helpful: number;
|
||||
isHelpful: boolean;
|
||||
replies: ReviewReply[];
|
||||
canReply: boolean;
|
||||
}
|
||||
|
||||
const Reviews = () => {
|
||||
const { user } = useAuth();
|
||||
const { toast } = useToast();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [replyingToReview, setReplyingToReview] = useState<string | null>(null);
|
||||
const [replyContent, setReplyContent] = useState('');
|
||||
const [showPhotoUpload, setShowPhotoUpload] = useState(false);
|
||||
const [selectedReviewForReply, setSelectedReviewForReply] = useState<Review | null>(null);
|
||||
const [reviews, setReviews] = useState<Review[]>([]);
|
||||
const [ratingStats, setRatingStats] = useState<ReviewStats>({
|
||||
average: 0,
|
||||
totalRatings: 0,
|
||||
totalReviews: 0,
|
||||
breakdown: {}
|
||||
});
|
||||
|
||||
// Sample reviews data with full functionality
|
||||
const [reviews, setReviews] = useState<Review[]>([
|
||||
{
|
||||
id: '1',
|
||||
itemId: 'item_001',
|
||||
userId: 'user_001',
|
||||
userName: 'Ethan Blackwood',
|
||||
userAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=center',
|
||||
rating: 3.5,
|
||||
comment: 'There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which.',
|
||||
images: [
|
||||
'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=200&h=200&fit=crop',
|
||||
'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=200&h=200&fit=crop',
|
||||
'https://images.unsplash.com/photo-1551632811-561732d1e306?w=200&h=200&fit=crop'
|
||||
],
|
||||
createdAt: '25 Oct 2023 at 12:27 pm',
|
||||
helpful: 16,
|
||||
isHelpful: false,
|
||||
canReply: true,
|
||||
replies: [
|
||||
{
|
||||
id: 'reply_1',
|
||||
authorId: 'owner_001',
|
||||
authorName: 'Hotel Owner',
|
||||
authorAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop&crop=center',
|
||||
content: 'Thank you for your feedback! We appreciate your honest review and are working to improve our services.',
|
||||
createdAt: '26 Oct 2023 at 10:15 am',
|
||||
images: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
itemId: 'item_001',
|
||||
userId: 'user_002',
|
||||
userName: 'Gabriel North',
|
||||
userAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=center',
|
||||
rating: 4.0,
|
||||
comment: 'This is some content from a media component. You can replace this with any content and adjust it as needed.',
|
||||
images: [],
|
||||
createdAt: '25 Oct 2023 at 12:27 pm',
|
||||
helpful: 16,
|
||||
isHelpful: true,
|
||||
canReply: true,
|
||||
replies: []
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
itemId: 'item_001',
|
||||
userId: 'user_003',
|
||||
userName: 'Pranoti Deshpande',
|
||||
userAvatar: 'https://images.unsplash.com/photo-1494790108755-2616b612b5bc?w=100&h=100&fit=crop&crop=center',
|
||||
rating: 3.5,
|
||||
comment: 'There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don\'t look even slightly believable.',
|
||||
images: [],
|
||||
createdAt: '25 Oct 2023 at 12:27 pm',
|
||||
helpful: 8,
|
||||
isHelpful: false,
|
||||
canReply: true,
|
||||
replies: []
|
||||
useEffect(() => {
|
||||
loadReviews();
|
||||
loadStats();
|
||||
}, []);
|
||||
|
||||
const loadReviews = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await reviewService.getReviews();
|
||||
setReviews(data);
|
||||
} catch (error) {
|
||||
console.error('Error loading reviews:', error);
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'Failed to load reviews',
|
||||
variant: 'destructive',
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
// Rating statistics
|
||||
const ratingStats = {
|
||||
average: 4.3,
|
||||
totalRatings: 2525,
|
||||
totalReviews: 293,
|
||||
breakdown: {
|
||||
5: { count: 1138, percentage: 45 },
|
||||
4: { count: 883, percentage: 35 },
|
||||
3: { count: 379, percentage: 15 },
|
||||
2: { count: 808, percentage: 32 },
|
||||
1: { count: 1742, percentage: 69 }
|
||||
const loadStats = async () => {
|
||||
try {
|
||||
const stats = await reviewService.getReviewStats();
|
||||
setRatingStats(stats);
|
||||
} catch (error) {
|
||||
console.error('Error loading stats:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -173,41 +111,57 @@ const Reviews = () => {
|
||||
return stars;
|
||||
};
|
||||
|
||||
const handleHelpfulClick = (reviewId: string) => {
|
||||
setReviews(prevReviews =>
|
||||
prevReviews.map(review =>
|
||||
review.id === reviewId
|
||||
? {
|
||||
...review,
|
||||
isHelpful: !review.isHelpful,
|
||||
helpful: review.isHelpful ? review.helpful - 1 : review.helpful + 1
|
||||
}
|
||||
: review
|
||||
)
|
||||
);
|
||||
const handleHelpfulClick = async (reviewId: string) => {
|
||||
try {
|
||||
await reviewService.markAsHelpful(reviewId);
|
||||
setReviews(prevReviews =>
|
||||
prevReviews.map(review =>
|
||||
review.id === reviewId
|
||||
? {
|
||||
...review,
|
||||
isHelpful: !review.isHelpful,
|
||||
helpful: review.isHelpful ? review.helpful - 1 : review.helpful + 1
|
||||
}
|
||||
: review
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error marking review as helpful:', error);
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'Failed to mark review as helpful',
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleReplySubmit = (reviewId: string, content: string, images: string[] = []) => {
|
||||
const newReply: ReviewReply = {
|
||||
id: `reply_${Date.now()}`,
|
||||
authorId: user?.id || 'current_user',
|
||||
authorName: user?.name || 'Business Owner',
|
||||
authorAvatar: user?.avatar || 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop&crop=center',
|
||||
content,
|
||||
createdAt: new Date().toLocaleString(),
|
||||
images
|
||||
};
|
||||
const handleReplySubmit = async (reviewId: string, content: string, images: string[] = []) => {
|
||||
try {
|
||||
const newReply = await reviewService.createReply(reviewId, content, images);
|
||||
|
||||
setReviews(prevReviews =>
|
||||
prevReviews.map(review =>
|
||||
review.id === reviewId
|
||||
? { ...review, replies: [...review.replies, newReply] }
|
||||
: review
|
||||
)
|
||||
);
|
||||
|
||||
setReviews(prevReviews =>
|
||||
prevReviews.map(review =>
|
||||
review.id === reviewId
|
||||
? { ...review, replies: [...review.replies, newReply] }
|
||||
: review
|
||||
)
|
||||
);
|
||||
toast({
|
||||
title: 'Success',
|
||||
description: 'Reply posted successfully',
|
||||
});
|
||||
|
||||
setReplyingToReview(null);
|
||||
setReplyContent('');
|
||||
setReplyingToReview(null);
|
||||
setReplyContent('');
|
||||
} catch (error) {
|
||||
console.error('Error posting reply:', error);
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'Failed to post reply',
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const openReplyDialog = (review: Review) => {
|
||||
|
||||
Reference in New Issue
Block a user