feat: cho phép người dùng và người quản lí xóa bình luận
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { X, Send, MessageSquare, User, Loader2 } from 'lucide-react';
|
||||
import { X, Send, MessageSquare, User, Loader2, Trash2 } from 'lucide-react';
|
||||
import { io } from 'socket.io-client';
|
||||
import { useTourStore } from '@/store/useTourStore';
|
||||
import { ConfirmModal } from './ConfirmModal';
|
||||
|
||||
interface Comment {
|
||||
id: string;
|
||||
userName: string;
|
||||
content: string;
|
||||
createdAt: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
interface CommentModalProps {
|
||||
@@ -15,13 +18,23 @@ interface CommentModalProps {
|
||||
locationId: string;
|
||||
locationName: string;
|
||||
onCommentAdded?: () => void; // Callback to update comment count on parent
|
||||
onCommentDeleted?: () => void;
|
||||
isPublicView?: boolean; // New prop to indicate public view
|
||||
}
|
||||
|
||||
export const CommentModal: React.FC<CommentModalProps> = ({ isOpen, onClose, locationId, locationName, onCommentAdded, isPublicView = false }) => {
|
||||
export const CommentModal: React.FC<CommentModalProps> = ({ isOpen, onClose, locationId, locationName, onCommentAdded, onCommentDeleted, isPublicView = false }) => {
|
||||
const [comments, setComments] = useState<Comment[]>([]);
|
||||
const [newComment, setNewComment] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [confirmState, setConfirmState] = useState<{ open: boolean; commentId: string }>({ open: false, commentId: '' });
|
||||
|
||||
const userRole = useTourStore(state => state.userRole);
|
||||
const currentUserId = React.useMemo(() => {
|
||||
try {
|
||||
const user = JSON.parse(localStorage.getItem('user') || '{}');
|
||||
return user.id;
|
||||
} catch { return null; }
|
||||
}, []);
|
||||
|
||||
const fetchComments = async () => {
|
||||
setIsLoading(true);
|
||||
@@ -39,7 +52,8 @@ export const CommentModal: React.FC<CommentModalProps> = ({ isOpen, onClose, loc
|
||||
id: c.id,
|
||||
userName: c.user?.name || 'Ẩn danh',
|
||||
content: c.content,
|
||||
createdAt: c.createdAt
|
||||
createdAt: c.createdAt,
|
||||
userId: c.userId
|
||||
})));
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -97,6 +111,23 @@ export const CommentModal: React.FC<CommentModalProps> = ({ isOpen, onClose, loc
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = async (commentId: string) => {
|
||||
try {
|
||||
const res = await fetch(`/api/v1/locations/comments/${commentId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||
}
|
||||
});
|
||||
if (res.ok) {
|
||||
setComments(prev => prev.filter(c => c.id !== commentId));
|
||||
onCommentDeleted?.();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Lỗi khi xóa bình luận:', error);
|
||||
}
|
||||
};
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
@@ -131,7 +162,17 @@ export const CommentModal: React.FC<CommentModalProps> = ({ isOpen, onClose, loc
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="bg-white p-3 rounded-2xl rounded-tl-none border border-gray-100 shadow-sm">
|
||||
<p className="text-xs font-black text-gray-900 mb-1">{c.userName}</p>
|
||||
<div className="flex justify-between items-start mb-1">
|
||||
<p className="text-xs font-black text-gray-900">{c.userName}</p>
|
||||
{(userRole === 'OWNER' || userRole === 'MANAGER' || c.userId === currentUserId) && (
|
||||
<button
|
||||
onClick={() => setConfirmState({ open: true, commentId: c.id })}
|
||||
className="text-gray-400 hover:text-red-500 transition-colors"
|
||||
>
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 leading-relaxed">{c.content}</p>
|
||||
</div>
|
||||
<p className="text-[10px] text-gray-400 mt-1 ml-1 font-medium">
|
||||
@@ -160,6 +201,17 @@ export const CommentModal: React.FC<CommentModalProps> = ({ isOpen, onClose, loc
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={confirmState.open}
|
||||
title="Xóa bình luận"
|
||||
message="Bạn có chắc chắn muốn xóa bình luận này không? Hành động này sẽ không thể hoàn tác."
|
||||
onConfirm={() => {
|
||||
handleDelete(confirmState.commentId);
|
||||
setConfirmState({ open: false, commentId: '' });
|
||||
}}
|
||||
onCancel={() => setConfirmState({ open: false, commentId: '' })}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user