diff --git a/src/pages/ticket/Detail.tsx b/src/pages/ticket/Detail.tsx index 4d7b124..1365b99 100644 --- a/src/pages/ticket/Detail.tsx +++ b/src/pages/ticket/Detail.tsx @@ -1,12 +1,11 @@ import { type FC, useMemo, useState } from "react"; -import { useNavigate, useParams } from "react-router-dom"; +import { useParams } from "react-router-dom"; import Input from "@/components/Input"; -import { Paths } from "@/config/Paths"; import { clx } from "@/helpers/utils"; import { t } from "@/locale"; import { getTicketDisplayName } from "./types/TicketTypes"; import type { TicketDetailType } from "./types/TicketTypes"; -import { useCreateOrReplyTicket, useGetTicketById } from "./hooks/useTicketData"; +import { useCloseTicket, useCreateOrReplyTicket, useGetTicketById } from "./hooks/useTicketData"; import { buildThreadItems, getStatusClass } from "./detailUtils"; import MessageBubble from "./MessageBubble"; import ReplyForm from "./ReplyForm"; @@ -16,13 +15,13 @@ import TicketDetailActions from "./TicketDetailActions"; const STATUS_CLOSED = "closed"; const TicketDetail: FC = () => { - const navigate = useNavigate(); const { id } = useParams<{ id: string }>(); const [content, setContent] = useState(""); const [files, setFiles] = useState([]); const getTicket = useGetTicketById(id ?? ""); const addMessage = useCreateOrReplyTicket(); + const closeTicket = useCloseTicket(); const ticket = getTicket.data?.data; const threadItems = useMemo( @@ -33,7 +32,15 @@ const TicketDetail: FC = () => { ticket?.status?.toLowerCase() === STATUS_CLOSED || ticket?.status?.toUpperCase() === "CLOSED"; - const handleCloseTicket = () => navigate(Paths.tickets.list); + const handleCloseTicket = () => { + if (!id) return; + closeTicket.mutate( + { id, params: { status: "closed" } }, + { + onSuccess: () => getTicket.refetch(), + } + ); + }; const handleSendReply = () => { if (!id || !ticket || !content.trim()) return; @@ -146,6 +153,7 @@ const TicketDetail: FC = () => { )} diff --git a/src/pages/ticket/TicketDetailActions.tsx b/src/pages/ticket/TicketDetailActions.tsx index 0b0836b..e9be87e 100644 --- a/src/pages/ticket/TicketDetailActions.tsx +++ b/src/pages/ticket/TicketDetailActions.tsx @@ -6,11 +6,13 @@ import { t } from "@/locale"; export type TicketDetailActionsProps = { onScrollToReply: () => void; onCloseTicket: () => void; + isClosing?: boolean; }; const TicketDetailActions: FC = ({ onScrollToReply, onCloseTicket, + isClosing = false, }) => (
diff --git a/src/pages/ticket/hooks/useTicketData.ts b/src/pages/ticket/hooks/useTicketData.ts index d9f36e5..dd569f2 100644 --- a/src/pages/ticket/hooks/useTicketData.ts +++ b/src/pages/ticket/hooks/useTicketData.ts @@ -1,6 +1,11 @@ import * as api from "../service/TicketService"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import { type AddMessageTicketType, type CreateTicketPayload, type CreateTicketType } from "../types/TicketTypes"; +import { + type AddMessageTicketType, + type CloseTicketParamsType, + type CreateTicketPayload, + type CreateTicketType, +} from "../types/TicketTypes"; export const useGetTickets = (status?: string) => { return useQuery({ @@ -82,7 +87,13 @@ export const useAddMessageTicket = (id: string) => { export const useCloseTicket = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: (id: string) => api.closeTicket(id), + mutationFn: ({ + id, + params, + }: { + id: string; + params: CloseTicketParamsType; + }) => api.closeTicket(id, params), onSuccess: () => { queryClient.refetchQueries({ queryKey: ["tickets"], diff --git a/src/pages/ticket/service/TicketService.ts b/src/pages/ticket/service/TicketService.ts index dfea1f0..ffc01cb 100644 --- a/src/pages/ticket/service/TicketService.ts +++ b/src/pages/ticket/service/TicketService.ts @@ -2,6 +2,7 @@ import type { AxiosProgressEvent } from "axios"; import axios from "@/config/axios"; import { type AddMessageTicketType, + type CloseTicketParamsType, type CreateTicketPayload, type CreateTicketType, type GetTicketByIdResponseType, @@ -92,7 +93,7 @@ export const addMessageTicket = async ( return data; }; -export const closeTicket = async (id: string) => { - const { data } = await axios.post(`/tickets/${id}/close`); +export const closeTicket = async (id: string, params: CloseTicketParamsType) => { + const { data } = await axios.patch(`/public/tickets/${id}/status`, params); return data; }; diff --git a/src/pages/ticket/types/TicketTypes.ts b/src/pages/ticket/types/TicketTypes.ts index c44f1f0..9f93325 100644 --- a/src/pages/ticket/types/TicketTypes.ts +++ b/src/pages/ticket/types/TicketTypes.ts @@ -32,7 +32,10 @@ export type TicketListItemType = { export type GetTicketsResponseType = BaseResponse; /** آیتم تیکت در children (user به‌صورت id یا null، admin برای تشخیص پیام ادمین/کاربر) */ -export type TicketDetailChildType = Omit & { +export type TicketDetailChildType = Omit< + TicketListItemType, + "user" | "children" +> & { user: string | null; /** null = پیام از کاربر، مقدار دارد = پیام از ادمین/کارشناس */ admin: string | null; @@ -96,4 +99,10 @@ export type TicketThreadItemType = { }; export const getTicketDisplayName = (user: TicketUserType): string => - [user.firstName, user.lastName].filter(Boolean).join(" ").trim() || user.phone || "-"; + [user.firstName, user.lastName].filter(Boolean).join(" ").trim() || + user.phone || + "-"; + +export type CloseTicketParamsType = { + status: string; +};