Add approve and answer functionality to Questions page

This commit is contained in:
hamid zarghami
2025-10-26 15:01:45 +03:30
parent 3d5eebc91e
commit 3925898855
4 changed files with 89 additions and 5 deletions
+28 -2
View File
@@ -1,5 +1,5 @@
import { type FC, useState } from 'react'
import { useGetProductQuestions } from './hooks/useProductData'
import { useGetProductQuestions, useApproveProductQuestion, useAnswerProductQuestion } from './hooks/useProductData'
import { type ProductQuestionType } from './types/Types'
import PageLoading from '../../components/PageLoading'
import Error from '../../components/Error'
@@ -14,7 +14,9 @@ const Questions: FC = () => {
const [currentPage, setCurrentPage] = useState(1);
const [selectedQuestion, setSelectedQuestion] = useState<ProductQuestionType | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const { data, isLoading, error } = useGetProductQuestions(currentPage);
const { data, isLoading, error, refetch } = useGetProductQuestions(currentPage);
const approveMutation = useApproveProductQuestion();
const answerMutation = useAnswerProductQuestion();
if (isLoading) {
return (
@@ -63,6 +65,26 @@ const Questions: FC = () => {
setSelectedQuestion(null);
};
const handleApproveQuestion = async (questionId: string) => {
try {
await approveMutation.mutateAsync(questionId);
await refetch();
handleCloseModal();
} catch (error) {
console.error('خطا در تایید سوال:', error);
}
};
const handleAnswerQuestion = async (questionId: string, answer: string) => {
try {
await answerMutation.mutateAsync({ id: questionId, answer });
await refetch();
handleCloseModal();
} catch (error) {
console.error('خطا در پاسخ به سوال:', error);
}
};
return (
<div>
<PageTitle />
@@ -152,6 +174,10 @@ const Questions: FC = () => {
isOpen={isModalOpen}
onClose={handleCloseModal}
question={selectedQuestion}
onApprove={handleApproveQuestion}
onAnswer={handleAnswerQuestion}
isApproving={approveMutation.isPending}
isAnswering={answerMutation.isPending}
/>
</div>
)
@@ -1,16 +1,19 @@
import { type FC } from 'react'
import { type FC, useState } from 'react'
import { type ProductQuestionType } from '../types/Types'
import DefaulModal from '../../../components/DefaulModal'
import StatusWithText from '../../../components/StatusWithText'
import { Button } from '@/components/ui/button'
import { TickCircle } from 'iconsax-react'
import { Textarea } from '@/components/Textarea'
import { TickCircle, Send } from 'iconsax-react'
interface QuestionModalProps {
isOpen: boolean
onClose: () => void
question: ProductQuestionType | null
onApprove?: (questionId: string) => void
onAnswer?: (questionId: string, answer: string) => void
isApproving?: boolean
isAnswering?: boolean
}
const QuestionModal: FC<QuestionModalProps> = ({
@@ -18,8 +21,11 @@ const QuestionModal: FC<QuestionModalProps> = ({
onClose,
question,
onApprove,
isApproving = false
onAnswer,
isApproving = false,
isAnswering = false
}) => {
const [answer, setAnswer] = useState('');
const getStatusVariant = (status: string) => {
switch (status) {
case 'accepted': return 'success';
@@ -44,6 +50,13 @@ const QuestionModal: FC<QuestionModalProps> = ({
}
};
const handleAnswer = () => {
if (question && onAnswer && answer.trim()) {
onAnswer(question._id, answer.trim());
setAnswer('');
}
};
return (
<DefaulModal
open={isOpen}
@@ -125,6 +138,29 @@ const QuestionModal: FC<QuestionModalProps> = ({
تاریخ ارسال: {question.createdAt}
</div>
{/* بخش پاسخ دادن */}
{onAnswer && (
<div className="bg-blue-50 p-4 rounded-lg border-t mt-4">
<h4 className="font-medium text-blue-900 mb-3">پاسخ به سوال:</h4>
<Textarea
value={answer}
onChange={(e) => setAnswer(e.target.value)}
placeholder="پاسخ خود را اینجا تایپ کنید..."
className="w-full min-h-[100px] mb-3"
/>
<div className="flex justify-end">
<Button
onClick={handleAnswer}
disabled={isAnswering || !answer.trim()}
className="bg-blue-600 hover:bg-blue-700 disabled:opacity-50"
>
<Send color="#fff" size={16} className="ml-2" />
{isAnswering ? 'در حال ارسال...' : 'ارسال پاسخ'}
</Button>
</div>
</div>
)}
{/* دکمه تایید */}
{question.status !== 'accepted' && onApprove && (
<div className="flex justify-end pt-4 border-t">
@@ -123,4 +123,16 @@ export const useGetProductQuestions = (page: number = 1, limit: number = 10) =>
queryKey: ['product-questions', page, limit],
queryFn: () => api.getProductQuestions(page, limit),
});
};
export const useApproveProductQuestion = () => {
return useMutation({
mutationFn: api.approveProductQuestion,
});
};
export const useAnswerProductQuestion = () => {
return useMutation({
mutationFn: api.answerProductQuestion,
});
};
@@ -117,4 +117,14 @@ export const getProductQuestions = async (page: number = 1, limit: number = 10):
const params: Record<string, string | number> = { page, limit };
const { data } = await axios.get(`admin/products/questions`, { params });
return data;
};
export const approveProductQuestion = async (id: string) => {
const { data } = await axios.post(`/admin/products/questions/${id}/approve`);
return data;
};
export const answerProductQuestion = async (params: {id: string, answer: string}) => {
const { data } = await axios.post(`/product/questions/${params.id}/answer`, { content:params.answer });
return data;
};