review admin

This commit is contained in:
hamid zarghami
2025-03-02 12:09:18 +03:30
parent 0cf7dede8b
commit cac446007f
9 changed files with 175 additions and 2 deletions
+104
View File
@@ -0,0 +1,104 @@
import { FC, useState } from 'react'
import { useChangeStatusReview, useGetReviews } from './hooks/useServiceData'
import { useTranslation } from 'react-i18next'
import Td from '../../components/Td'
import { ReviewItemType } from './types/ServiceTypes'
import moment from 'moment-jalaali'
import Button from '../../components/Button'
import { CloseCircle, TickCircle } from 'iconsax-react'
enum ReviewStatusEnum {
PENDING = 'PENDING',
APPROVED = 'APPROVED',
REJECTED = 'REJECTED'
}
const Reviews: FC = () => {
const { t } = useTranslation('global')
const [loadingType, setLoadingType] = useState<ReviewStatusEnum>(ReviewStatusEnum.PENDING)
const [loadingId, setLoadingId] = useState<string>('')
const getReviews = useGetReviews()
const changeStatusReview = useChangeStatusReview()
const handleChange = (status: ReviewStatusEnum, id: string) => {
setLoadingType(status)
setLoadingId(id)
changeStatusReview.mutate({ status, id }, {
onSuccess: () => {
getReviews.refetch()
}
})
}
return (
<div className='mt-4'>
<div className='relative overflow-x-auto rounded-3xl mt-9 w-full'>
<table className='w-full text-sm '>
<thead className='thead'>
<tr>
<Td text={t('review.title')} />
<Td text={t('review.comment')} />
<Td text={t('review.user')} />
<Td text={t('review.service')} />
<Td text={t('review.date')} />
<Td text={t('review.status')} />
</tr>
</thead>
<tbody>
{
getReviews.data?.data?.reviews?.map((item: ReviewItemType) => (
<tr className='tr'>
<Td text={item.title} />
<Td text={item.comment} />
<Td text={item.user?.firstName + ' ' + item.user.lastName} />
<Td text={item.service?.name} />
<Td text={''}>
<div className='dltr text-right'>
{moment(item.createdAt).format('jYYYY-jMM-jDD HH:mm')}
</div>
</Td>
<Td text={''}>
{
item.status === 'PENDING' ?
<div className='flex gap-2'>
<Button
className='bg-green-500 text-xs h-7 w-fit px-3 text-white'
onClick={() => handleChange(ReviewStatusEnum.APPROVED, item.id)}
isLoading={changeStatusReview.isPending && loadingType === ReviewStatusEnum.APPROVED && item.id === loadingId}
>
<div className='flex gap-1.5 items-center'>
<TickCircle size={16} color='white' />
<div>
{t('review.approve')}
</div>
</div>
</Button>
<Button
className='bg-red-500 text-xs h-7 w-fit px-3 text-white'
onClick={() => handleChange(ReviewStatusEnum.REJECTED, item.id)}
isLoading={changeStatusReview.isPending && loadingType === ReviewStatusEnum.REJECTED && item.id === loadingId}
>
<div className='flex gap-1.5 items-center'>
<CloseCircle size={16} color='white' />
<div>
{t('review.reject')}
</div>
</div>
</Button>
</div>
:
t('review.' + item.status.toLowerCase())
}
</Td>
</tr>
))
}
</tbody>
</table>
</div>
</div>
)
}
export default Reviews
+14
View File
@@ -132,3 +132,17 @@ export const useUpdatePlan = (id: string) => {
mutationFn: (variables: UpdatePlanType) => api.updatePlan(id, variables),
});
};
export const useGetReviews = (page: number = 1) => {
return useQuery({
queryKey: ["reviews", page],
queryFn: () => api.getReviews(page),
});
};
export const useChangeStatusReview = () => {
return useMutation({
mutationFn: (variables: { status: string; id: string }) =>
api.changeStatusReview(variables),
});
};
@@ -115,3 +115,18 @@ export const updatePlan = async (id: string, params: UpdatePlanType) => {
const { data } = await axios.patch(`/subscriptions/${id}`, params);
return data;
};
export const getReviews = async (page: number) => {
const { data } = await axios.get(`/danak-services/reviews?page=${page}`);
return data;
};
export const changeStatusReview = async (params: {
status: string;
id: string;
}) => {
const { data } = await axios.patch(
`/danak-services/reviews/${params.id}/${params.status}`
);
return data;
};
+19
View File
@@ -82,3 +82,22 @@ export type UpdatePlanType = {
isActive?: boolean;
serviceId?: string;
};
export type ReviewItemType = {
id: string;
comment: string;
createdAt: string;
rating: number;
service: {
id: string;
name: string;
};
status: "APPROVED" | "PENDING" | "REJECTED";
title: string;
user: {
id: string;
firstName: string;
lastName: string;
profilePic: string;
};
};