import { useState, type ChangeEvent } from 'react' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' import { toast } from '@/shared/ui/toast-store' import { Button } from '@/shared/ui/button' import { Textarea } from '@/shared/ui/textarea' import { Input } from '@/shared/ui/input' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/shared/ui/dialog' import { HttpError } from '@/shared/api/client' import { TicketStatusBadge } from './TicketStatusBadge' import { TicketAttachmentImage } from './TicketAttachmentImage' import { addTicketComment, getTicket, reopenTicket } from './api' const MAX_FILES = 5 export function TicketDetailDialog({ ticketId, onOpenChange }: { ticketId: string; onOpenChange: (open: boolean) => void }) { const { t } = useTranslation() const queryClient = useQueryClient() const [reply, setReply] = useState('') const [files, setFiles] = useState([]) const { data, isLoading } = useQuery({ queryKey: ['ticket', ticketId], queryFn: () => getTicket(ticketId) }) const invalidate = async () => { await queryClient.invalidateQueries({ queryKey: ['ticket', ticketId] }) await queryClient.invalidateQueries({ queryKey: ['my-tickets'] }) } const replyMutation = useMutation({ mutationFn: () => addTicketComment(ticketId, reply.trim(), files), onSuccess: async () => { setReply('') setFiles([]) await invalidate() }, onError: (error) => toast.error(error instanceof HttpError ? error.detail : t('auth.genericError')), }) const reopenMutation = useMutation({ mutationFn: () => reopenTicket(ticketId), onSuccess: async () => { toast.success(t('support.reopened')) await invalidate() }, onError: () => toast.error(t('auth.genericError')), }) const handleFilesChange = (e: ChangeEvent) => { setFiles(Array.from(e.target.files ?? []).slice(0, MAX_FILES)) } return ( {data && } {data && t(`support.type.${data.type}`)} {isLoading &&

} {data && (
{data.type === 'RoleRequest' && (
{data.requestedRoleName ? t('support.requestedExistingRole', { role: data.requestedRoleName }) : t('support.requestedNewRole', { name: data.proposedRoleName, configs: data.proposedMaxConfigs, ip: data.proposedMaxIpLimit, })}
)}
{data.comments.map((comment) => (
{comment.authorName} {new Date(comment.createdAt).toLocaleString()}

{comment.body}

{comment.attachments.length > 0 && (
{comment.attachments.map((attachment) => ( ))}
)}
))}
{data.status === 'Resolved' && ( )} {data.status !== 'Closed' && (
{ e.preventDefault() if (reply.trim()) replyMutation.mutate() }} >