129 lines
4.9 KiB
TypeScript
129 lines
4.9 KiB
TypeScript
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
|