Files
dmenu-admin/src/pages/review/components/ReviewReplySection.tsx
T
morteza 3e17cf9e12
deploy to danak / build_and_deploy (push) Has been cancelled
review
2026-07-17 10:18:55 +03:30

129 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { type FC, useEffect, useState } from 'react'
import { MessageText1 } from 'iconsax-react'
import Textarea from '@/components/Textarea'
import Button from '@/components/Button'
import { formatOptionalDate } from '@/helpers/func'
import { toast } from 'react-toastify'
import { extractErrorMessage } from '@/config/func'
import { useDeleteReviewReply, useReplyToReview } from '../hooks/useReviewData'
import type { ReviewReply } from '../types/Types'
interface ReviewReplySectionProps {
reviewId: string
replies: ReviewReply[]
}
const ReviewReplySection: FC<ReviewReplySectionProps> = ({ reviewId, replies }) => {
const existingReply = replies[0]
const [comment, setComment] = useState(existingReply?.comment || '')
const replyMutation = useReplyToReview()
const deleteMutation = useDeleteReviewReply()
useEffect(() => {
setComment(existingReply?.comment || '')
}, [existingReply?.comment, existingReply?.id])
const hasChanges = comment.trim() !== (existingReply?.comment || '').trim()
const canSave = comment.trim().length > 0 && hasChanges
const handleSave = () => {
if (!canSave) return
replyMutation.mutate(
{ id: reviewId, comment: comment.trim() },
{
onSuccess: () => {
toast.success(existingReply ? 'پاسخ با موفقیت به‌روزرسانی شد' : 'پاسخ با موفقیت ثبت شد')
},
onError: (error) => {
toast.error(extractErrorMessage(error))
},
}
)
}
const handleDelete = () => {
deleteMutation.mutate(reviewId, {
onSuccess: () => {
setComment('')
toast.success('پاسخ حذف شد')
},
onError: (error) => {
toast.error(extractErrorMessage(error))
},
})
}
return (
<div className='pt-6 border-t border-border space-y-6'>
<div className='flex items-center gap-2'>
<MessageText1 size={20} color="#8C90A3" />
<span className='text-sm font-medium'>پاسخ رستوران</span>
{replies.length > 0 && (
<span className='text-xs text-gray-400'>({replies.length})</span>
)}
</div>
{replies.length > 0 && (
<div className='space-y-3'>
{replies.map((reply) => (
<div
key={reply.id}
className='bg-gray-50 rounded-xl p-4 border border-border'
>
<div className='flex items-center justify-between mb-2'>
<span className='text-xs font-medium text-gray-500'>پاسخ</span>
{reply.createdAt && (
<span className='text-xs text-gray-500'>
{formatOptionalDate(reply.createdAt, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
})}
</span>
)}
</div>
<p className='text-sm leading-6 text-gray-700 whitespace-pre-wrap'>
{reply.comment || '-'}
</p>
</div>
))}
</div>
)}
<div>
<Textarea
label='متن پاسخ'
isNotRequired
placeholder='پاسخ خود را به این نظر بنویسید...'
value={comment}
onChange={(e) => setComment(e.target.value)}
rows={4}
/>
<div className='flex items-center gap-3 mt-4'>
<Button
label={existingReply ? 'ویرایش پاسخ' : 'ثبت پاسخ'}
onClick={handleSave}
isloading={replyMutation.isPending}
disabled={!canSave}
className='w-36'
/>
{existingReply && (
<Button
label='حذف پاسخ'
onClick={handleDelete}
isloading={deleteMutation.isPending}
className='w-28 bg-red-500 hover:bg-red-600'
/>
)}
</div>
</div>
</div>
)
}
export default ReviewReplySection