import { request } from "@/lib/api/client" import type { Tag } from "@/lib/api/admin" export type Paging = { page: number limit: number total: number } export type PageResult = { results: T[] page: Paging } export type TicketCustomer = { id: number name: string companyId?: number company?: { id: number name: string code?: string remark?: string createdAt?: string updatedAt?: string } primaryMobile?: string primaryEmail?: string } export type TicketSLA = { slaType: string targetMinutes: number status: string startedAt?: string pausedAt?: string stoppedAt?: string breachedAt?: string elapsedMin: number } export type TicketComment = { id: number ticketId: number commentType: string authorType: string authorId: number authorName?: string contentType: string content: string payload?: string createdAt?: string } export type TicketEvent = { id: number ticketId: number eventType: string operatorType: string operatorId: number operatorName?: string oldValue?: string newValue?: string content?: string payload?: string createdAt?: string } export type TicketItem = { id: number ticketNo: string title: string description: string source: string channel: string customerId: number conversationId: number tags?: Tag[] type: string priority: number priorityName?: string severity: number status: string currentTeamId: number currentTeamName?: string currentAssigneeId: number currentAssigneeName?: string watchedByMe: boolean pendingReason?: string closeReason?: string resolutionCode?: string resolutionCodeName?: string resolutionSummary?: string firstResponseAt?: string resolvedAt?: string closedAt?: string dueAt?: string nextReplyDeadlineAt?: string resolveDeadlineAt?: string reopenedCount: number createdAt?: string updatedAt?: string customer?: TicketCustomer sla?: TicketSLA[] } export type TicketDetail = { ticket: TicketItem watchers?: Array<{ id: number userId: number userName?: string }> collaborators?: TicketCollaborator[] comments?: TicketComment[] events?: TicketEvent[] relatedTickets?: TicketRelation[] } export type TicketCollaborator = { id: number userId: number userName?: string teamName?: string } export type TicketRelation = { id: number ticketId: number relatedTicketId: number relationType: string relatedTicketNo?: string relatedTicketTitle?: string relatedTicketStatus?: string currentTeamName?: string currentAssigneeName?: string updatedAt?: string } export type TicketSummary = { all: number mine: number watching: number collaboration: number participating: number mentioned: number unassigned: number pendingCustomer: number pendingInternal: number overdue: number } export type TicketRiskReason = { code: string title: string description: string count: number } export type TicketRiskOverview = { overdue: number highRisk: number unassigned: number pendingInternal: number pendingCustomer: number riskWindowMins: number reasons?: TicketRiskReason[] } export type TicketSavedView = { id: number name: string filters?: Record sortNo: number } export type TicketListQuery = { page?: number limit?: number keyword?: string status?: string priority?: number severity?: number tagId?: number currentTeamId?: number currentAssigneeId?: number customerId?: number conversationId?: number source?: string watching?: number collaboration?: number collaborating?: number mentioned?: number mine?: number unassigned?: number overdue?: number } export type TicketRiskListQuery = { riskType: "overdue" | "high_risk" | "unassigned" | "pending_internal" | "pending_customer" currentTeamId?: number riskWindowMins?: number page?: number limit?: number } export type CreateTicketPayload = { title: string description: string source?: string channel?: string customerId?: number conversationId?: number tagIds?: number[] type?: string priority: number severity: number currentTeamId?: number currentAssigneeId?: number dueAt?: string customFields?: Record } export type CreateTicketFromConversationPayload = { conversationId: number title: string description: string tagIds?: number[] priority: number severity: number currentTeamId?: number currentAssigneeId?: number syncToConversation: boolean customFields?: Record } export type UpdateTicketPayload = { ticketId: number title: string description: string tagIds?: number[] type?: string priority: number severity: number currentTeamId?: number currentAssigneeId?: number dueAt?: string customFields?: Record } function toQueryString(query?: Record) { if (!query) { return "" } const params = new URLSearchParams() Object.entries(query).forEach(([key, value]) => { if (value === undefined || value === "") { return } params.set(key, String(value)) }) const output = params.toString() return output ? `?${output}` : "" } export function fetchTickets(query?: TicketListQuery) { return request>(`/api/console/ticket/list${toQueryString(query)}`) } export function fetchTicketDetail(id: number) { return request(`/api/console/ticket/${id}`) } export function fetchTicketSummary() { return request("/api/console/ticket/summary") } export function fetchTicketViews() { return request("/api/console/ticket/view_list") } export function saveTicketView(payload: { id?: number name: string filters?: Record }) { return request("/api/console/ticket/save_view", { method: "POST", body: JSON.stringify(payload), }) } export function deleteTicketView(id: number) { return request("/api/console/ticket/delete_view", { method: "POST", body: JSON.stringify({ id }), }) } export function fetchTicketRiskOverview(query?: { currentTeamId?: number riskWindowMins?: number }) { return request(`/api/console/ticket/risk_overview${toQueryString(query)}`) } export function fetchTicketRiskList(query: TicketRiskListQuery) { return request>(`/api/console/ticket/risk_list${toQueryString(query)}`) } export function createTicket(payload: CreateTicketPayload) { return request("/api/console/ticket/create", { method: "POST", body: JSON.stringify(payload), }) } export function createTicketFromConversation(payload: CreateTicketFromConversationPayload) { return request("/api/console/ticket/create_from_conversation", { method: "POST", body: JSON.stringify(payload), }) } export function updateTicket(payload: UpdateTicketPayload) { return request("/api/console/ticket/update", { method: "POST", body: JSON.stringify(payload), }) } export function linkTicketToCustomer(payload: { ticketId: number customerId: number }) { return request("/api/console/ticket/link_customer", { method: "POST", body: JSON.stringify(payload), }) } export function assignTicket(payload: { ticketId: number toUserId: number toTeamId?: number reason?: string }) { return request("/api/console/ticket/assign", { method: "POST", body: JSON.stringify(payload), }) } export function batchAssignTickets(payload: { ticketIds: number[] toUserId: number toTeamId?: number reason?: string }) { return request("/api/console/ticket/batch_assign", { method: "POST", body: JSON.stringify(payload), }) } export function changeTicketStatus(payload: { ticketId: number status: string pendingReason?: string closeReason?: string resolutionCode?: string resolutionSummary?: string reason?: string }) { return request("/api/console/ticket/change_status", { method: "POST", body: JSON.stringify(payload), }) } export function batchChangeTicketStatus(payload: { ticketIds: number[] status: string pendingReason?: string closeReason?: string resolutionCode?: string resolutionSummary?: string reason?: string }) { return request("/api/console/ticket/batch_change_status", { method: "POST", body: JSON.stringify(payload), }) } export function replyTicket(payload: { ticketId: number contentType?: string content: string payload?: string }) { return request("/api/console/ticket/reply", { method: "POST", body: JSON.stringify(payload), }) } export function addTicketInternalNote(payload: { ticketId: number contentType?: string content: string payload?: string }) { return request("/api/console/ticket/internal_note", { method: "POST", body: JSON.stringify(payload), }) } export function closeTicket(payload: { ticketId: number; closeReason: string }) { return request("/api/console/ticket/close", { method: "POST", body: JSON.stringify(payload), }) } export function reopenTicket(payload: { ticketId: number; reason: string }) { return request("/api/console/ticket/reopen", { method: "POST", body: JSON.stringify(payload), }) } export function watchTicket(ticketId: number) { return request("/api/console/ticket/watch", { method: "POST", body: JSON.stringify({ ticketId }), }) } export function unwatchTicket(ticketId: number) { return request("/api/console/ticket/unwatch", { method: "POST", body: JSON.stringify({ ticketId }), }) } export function batchWatchTickets(payload: { ticketIds: number[]; watched: boolean }) { return request("/api/console/ticket/batch_watch", { method: "POST", body: JSON.stringify(payload), }) } export function addTicketRelation(payload: { ticketId: number relatedTicketId?: number relatedTicketNo?: string relationType: string }) { return request("/api/console/ticket/add_relation", { method: "POST", body: JSON.stringify(payload), }) } export function deleteTicketRelation(payload: { ticketId: number; relationId: number }) { return request("/api/console/ticket/delete_relation", { method: "POST", body: JSON.stringify(payload), }) } export function addTicketCollaborator(payload: { ticketId: number; userId: number }) { return request("/api/console/ticket/add_collaborator", { method: "POST", body: JSON.stringify(payload), }) } export function deleteTicketCollaborator(payload: { ticketId: number; collaboratorId: number }) { return request("/api/console/ticket/delete_collaborator", { method: "POST", body: JSON.stringify(payload), }) }