review admin
This commit is contained in:
@@ -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
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user