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 { type FC, useState } from 'react'
import { useGetProductQuestions } from './hooks/useProductData' import { useGetProductQuestions, useApproveProductQuestion, useAnswerProductQuestion } from './hooks/useProductData'
import { type ProductQuestionType } from './types/Types' import { type ProductQuestionType } from './types/Types'
import PageLoading from '../../components/PageLoading' import PageLoading from '../../components/PageLoading'
import Error from '../../components/Error' import Error from '../../components/Error'
@@ -14,7 +14,9 @@ const Questions: FC = () => {
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [selectedQuestion, setSelectedQuestion] = useState<ProductQuestionType | null>(null); const [selectedQuestion, setSelectedQuestion] = useState<ProductQuestionType | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false); 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) { if (isLoading) {
return ( return (
@@ -63,6 +65,26 @@ const Questions: FC = () => {
setSelectedQuestion(null); 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 ( return (
<div> <div>
<PageTitle /> <PageTitle />
@@ -152,6 +174,10 @@ const Questions: FC = () => {
isOpen={isModalOpen} isOpen={isModalOpen}
onClose={handleCloseModal} onClose={handleCloseModal}
question={selectedQuestion} question={selectedQuestion}
onApprove={handleApproveQuestion}
onAnswer={handleAnswerQuestion}
isApproving={approveMutation.isPending}
isAnswering={answerMutation.isPending}
/> />
</div> </div>
) )
@@ -1,16 +1,19 @@
import { type FC } from 'react' import { type FC, useState } from 'react'
import { type ProductQuestionType } from '../types/Types' import { type ProductQuestionType } from '../types/Types'
import DefaulModal from '../../../components/DefaulModal' import DefaulModal from '../../../components/DefaulModal'
import StatusWithText from '../../../components/StatusWithText' import StatusWithText from '../../../components/StatusWithText'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { TickCircle } from 'iconsax-react' import { Textarea } from '@/components/Textarea'
import { TickCircle, Send } from 'iconsax-react'
interface QuestionModalProps { interface QuestionModalProps {
isOpen: boolean isOpen: boolean
onClose: () => void onClose: () => void
question: ProductQuestionType | null question: ProductQuestionType | null
onApprove?: (questionId: string) => void onApprove?: (questionId: string) => void
onAnswer?: (questionId: string, answer: string) => void
isApproving?: boolean isApproving?: boolean
isAnswering?: boolean
} }
const QuestionModal: FC<QuestionModalProps> = ({ const QuestionModal: FC<QuestionModalProps> = ({
@@ -18,8 +21,11 @@ const QuestionModal: FC<QuestionModalProps> = ({
onClose, onClose,
question, question,
onApprove, onApprove,
isApproving = false onAnswer,
isApproving = false,
isAnswering = false
}) => { }) => {
const [answer, setAnswer] = useState('');
const getStatusVariant = (status: string) => { const getStatusVariant = (status: string) => {
switch (status) { switch (status) {
case 'accepted': return 'success'; 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 ( return (
<DefaulModal <DefaulModal
open={isOpen} open={isOpen}
@@ -125,6 +138,29 @@ const QuestionModal: FC<QuestionModalProps> = ({
تاریخ ارسال: {question.createdAt} تاریخ ارسال: {question.createdAt}
</div> </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 && ( {question.status !== 'accepted' && onApprove && (
<div className="flex justify-end pt-4 border-t"> <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], queryKey: ['product-questions', page, limit],
queryFn: () => api.getProductQuestions(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 params: Record<string, string | number> = { page, limit };
const { data } = await axios.get(`admin/products/questions`, { params }); const { data } = await axios.get(`admin/products/questions`, { params });
return data; 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;
}; };