-
+ :
+
+
-
-
-
- {t('ticket.info_ticket')}
-
-
- {t('ticket.answered')}
+
+
+ {getMessages.data?.data?.ticket?.subject}
+
+ {
+ getMessages.data?.data?.messages.map((item: any) => {
+ if (item?.author?.role?.name === 'user') {
+ return (
+
+
+ {item.content}
+
+
+ {moment(item.createdAt).format('jYYYY-jMM-jDD HH:mm')}
+
+
+ )
+ } else {
+ return (
+
+
+
+
+ {t('ticket.expert')}
+
+
{item.author?.firstName + ' ' + item?.author?.lastName}
+
+
+ {item.content}
+
+
+ 10:07 | 1403/09/30
+
+
+
+ )
+ }
+ })
+ }
+
+
+
+ {
+ getMessages.data?.data?.ticket?.status !== 'CLOSED' &&
+
+
+
+
+
+
+
+
+
+
+ formik.handleSubmit()}
+ isLoading={addMessage.isPending || multiUpload.isPending}
+ />
+
+
+ }
+
+
+ {
+ getMessages.data?.data?.ticket?.status !== 'CLOSED' &&
+
+
+
+
+
+
+ {t('ticket.close_ticket')}
+
+
+
+
+ }
+
+
+
+ {t('ticket.info_ticket')}
+
+
+ {t(`ticket.${getMessages.data?.data?.ticket?.status}`)}
+
+
-
-
-
{t('ticket.ticket_number')}
-
- ۱۲۳۴۵۵
-
-
-
-
{t('ticket.ticket_number')}
-
- ۱۲۳۴۵۵
-
-
-
-
{t('ticket.ticket_number')}
-
- ۱۲۳۴۵۵
-
-
-
-
{t('ticket.ticket_number')}
-
- ۱۲۳۴۵۵
-
-
+
+
+
{t('ticket.ticket_number')}
+
+ {getMessages.data?.data?.ticket?.numericId}
+
+
+
+
{t('ticket.asignto')}
+
+ {getMessages.data?.data?.ticket?.assignedTo ? getMessages.data?.data?.ticket?.assignedTo?.firstName + ' ' + getMessages.data?.data?.ticket?.assignedTo?.lastName : ''}
+
+
+
+
{t('date')}
+
+ {moment(getMessages.data?.data?.ticket?.createdAt).format('jYYYY/jMM/jDD HH:mm')}
+
+
+
+
{t('ticket.category')}
+
+ {getMessages.data?.data?.ticket?.category?.title}
+
+
+
+
{t('ticket.priority')}
+
+ {getMessages.data?.data?.ticket?.priority === 'low' ? t('ticket.low') : getMessages.data?.data?.ticket?.priority === 'medium' ? t('ticket.medium') : t('ticket.high')}
+
+
-
+
-
-
-
- {t('ticket.update_sms')}
+
+
+
+ {t('ticket.update_sms')}
+
+
-
-
+ }
)
}
diff --git a/src/pages/ticket/TicketList.tsx b/src/pages/ticket/TicketList.tsx
index 994474e..002ddaf 100644
--- a/src/pages/ticket/TicketList.tsx
+++ b/src/pages/ticket/TicketList.tsx
@@ -1,16 +1,19 @@
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Button from '../../components/Button'
-import { Add, Eye, Message2, MessageRemove, MessageTick, MessageTime } from 'iconsax-react'
+import { Add, Eye, MessageRemove, MessageTick, MessageTime } from 'iconsax-react'
import Tabs from '../../components/Tabs'
import Td from '../../components/Td'
import { Link } from 'react-router-dom'
import { Pages } from '../../config/Pages'
+import { useGetTickets } from './hooks/useTicketData'
+import moment from 'moment-jalaali'
const TicketList: FC = () => {
const { t } = useTranslation('global')
- const [activeTab, setActiveTab] = useState
('answered')
+ const [activeTab, setActiveTab] = useState<'ANSWERED' | 'PENDING' | 'CLOSED'>('ANSWERED')
+ const getTickets = useGetTickets(activeTab)
return (
@@ -38,27 +41,27 @@ const TicketList: FC = () => {
active={activeTab}
items={[
{
- icon: ,
+ icon: ,
label: t('ticket.answered'),
- value: 'answered'
+ value: 'ANSWERED'
},
{
- icon: ,
+ icon: ,
label: t('ticket.checking'),
- value: 'checking'
+ value: 'PENDING'
},
+ // {
+ // icon: ,
+ // label: t('ticket.wait_answered'),
+ // value: 'wating'
+ // },
{
- icon: ,
- label: t('ticket.wait_answered'),
- value: 'wating'
- },
- {
- icon: ,
+ icon: ,
label: t('ticket.closed'),
- value: 'closed'
+ value: 'CLOSED'
},
]}
- onChange={setActiveTab}
+ onChange={(value) => setActiveTab(value as 'ANSWERED' | 'PENDING' | 'CLOSED')}
/>
@@ -77,34 +80,28 @@ const TicketList: FC = () => {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {
+ getTickets.data?.data?.tickets?.map((item: any) => (
+
+
+
+
+
+
+ {moment(item.updatedAt).format('jYYYY-jMM-jDD HH:mm')}
+
+
+
+
+
+
+
+
+
+
+
+ ))
+ }
diff --git a/src/pages/ticket/hooks/useTicketData.ts b/src/pages/ticket/hooks/useTicketData.ts
new file mode 100644
index 0000000..7587f58
--- /dev/null
+++ b/src/pages/ticket/hooks/useTicketData.ts
@@ -0,0 +1,62 @@
+import * as api from "../service/TicketService";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import { AddMessageTicketType, CreateTicketType } from "../types/TicketTypes";
+
+export const useGetTickets = (status: string) => {
+ return useQuery({
+ queryKey: ["tickets", status],
+ queryFn: () => api.getTickets(status),
+ });
+};
+
+export const useCreateTicket = () => {
+ return useMutation({
+ mutationFn: (variables: CreateTicketType) => api.createTicket(variables),
+ });
+};
+
+export const useGetCategoriesTicket = () => {
+ return useQuery({
+ queryKey: ["category-tickets"],
+ queryFn: () => api.getCategoriesTicket(),
+ });
+};
+
+export const useSingleUpload = () => {
+ return useMutation({
+ mutationFn: (variables: FormData) => api.uploadSingle(variables),
+ });
+};
+export const useMultiUpload = () => {
+ return useMutation({
+ mutationFn: (variables: FormData) => api.uploadMultiple(variables),
+ });
+};
+
+export const useGetMessages = (id: string) => {
+ return useQuery({
+ queryKey: ["ticket-messages", id],
+ queryFn: () => api.getMessages(id),
+ enabled: !!id,
+ });
+};
+
+export const useAddMessageTicket = (id: string) => {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (variables: AddMessageTicketType) =>
+ api.addMessageTicket(id, variables),
+ onSuccess: () => {
+ queryClient.refetchQueries({
+ queryKey: ["ticket-messages", id],
+ });
+ },
+ });
+};
+
+export const useCloseTicket = () => {
+ return useMutation({
+ mutationFn: (id: string) => api.closeTicket(id),
+ });
+};
diff --git a/src/pages/ticket/service/TicketService.ts b/src/pages/ticket/service/TicketService.ts
new file mode 100644
index 0000000..440f759
--- /dev/null
+++ b/src/pages/ticket/service/TicketService.ts
@@ -0,0 +1,45 @@
+import axios from "../../../config/axios";
+import { AddMessageTicketType, CreateTicketType } from "../types/TicketTypes";
+
+export const getTickets = async (status: string) => {
+ const { data } = await axios.get(`/tickets?status=${status}`);
+ return data;
+};
+
+export const createTicket = async (params: CreateTicketType) => {
+ const { data } = await axios.post(`/tickets`, params);
+ return data;
+};
+
+export const getCategoriesTicket = async () => {
+ const { data } = await axios.get(`/tickets/categories`);
+ return data;
+};
+
+export const uploadSingle = async (params: FormData) => {
+ const { data } = await axios.post(`/uploader/single-file`, params);
+ return data;
+};
+
+export const uploadMultiple = async (params: FormData) => {
+ const { data } = await axios.post(`/uploader/multi-file`, params);
+ return data;
+};
+
+export const getMessages = async (id: string) => {
+ const { data } = await axios.get(`/tickets/${id}/messages`);
+ return data;
+};
+
+export const addMessageTicket = async (
+ id: string,
+ params: AddMessageTicketType
+) => {
+ const { data } = await axios.post(`/tickets/${id}/messages`, params);
+ return data;
+};
+
+export const closeTicket = async (id: string) => {
+ const { data } = await axios.post(`/tickets/${id}/close`);
+ return data;
+};
diff --git a/src/pages/ticket/types/TicketTypes.ts b/src/pages/ticket/types/TicketTypes.ts
new file mode 100644
index 0000000..2eb7198
--- /dev/null
+++ b/src/pages/ticket/types/TicketTypes.ts
@@ -0,0 +1,14 @@
+export type CreateTicketType = {
+ title: string;
+ subject: string;
+ priority: "LOW" | "MEDIUM" | "HIGH";
+ danakServiceId?: string;
+ categoryId: string;
+ message: string;
+ attachmentUrls?: string[];
+};
+
+export type AddMessageTicketType = {
+ content: string;
+ attachmentUrls?: string[];
+};