feat: melhorias no vínculo de tickets e exportação
This commit is contained in:
parent
1b32638eb5
commit
9495b54a28
7 changed files with 226 additions and 16 deletions
|
|
@ -1,9 +1,10 @@
|
|||
"use client"
|
||||
|
||||
import Link from "next/link"
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { format, formatDistanceToNow } from "date-fns"
|
||||
import { ptBR } from "date-fns/locale"
|
||||
import { IconClock, IconDownload, IconPlayerPause, IconPlayerPlay, IconPencil } from "@tabler/icons-react"
|
||||
import { IconClock, IconDownload, IconLink, IconPlayerPause, IconPlayerPlay, IconPencil } from "@tabler/icons-react"
|
||||
import { useMutation, useQuery } from "convex/react"
|
||||
import { toast } from "sonner"
|
||||
import { api } from "@/convex/_generated/api"
|
||||
|
|
@ -283,6 +284,39 @@ export function TicketSummaryHeader({ ticket }: TicketHeaderProps) {
|
|||
}, [selectedCategoryId, selectedSubcategoryId, currentCategoryId, currentSubcategoryId])
|
||||
const currentQueueName = ticket.queue ?? ""
|
||||
const isAvulso = Boolean(((ticket.company ?? null) as { isAvulso?: boolean } | null)?.isAvulso ?? false)
|
||||
const resolvedWithSummary = useMemo(() => {
|
||||
if (!ticket.resolvedWithTicketId) return null
|
||||
const linkedId = String(ticket.resolvedWithTicketId)
|
||||
let reference: string | null = null
|
||||
let subject: string | null = null
|
||||
for (const event of ticket.timeline ?? []) {
|
||||
if (!event || event.type !== "TICKET_LINKED") continue
|
||||
const payload = (event.payload ?? {}) as {
|
||||
linkedTicketId?: unknown
|
||||
linkedReference?: unknown
|
||||
linkedSubject?: unknown
|
||||
}
|
||||
if (String(payload.linkedTicketId ?? "") !== linkedId) continue
|
||||
if (reference === null) {
|
||||
const rawReference = payload.linkedReference
|
||||
if (typeof rawReference === "number") {
|
||||
reference = rawReference.toString()
|
||||
} else if (typeof rawReference === "string" && rawReference.trim().length > 0) {
|
||||
reference = rawReference.trim()
|
||||
}
|
||||
}
|
||||
if (subject === null) {
|
||||
const rawSubject = payload.linkedSubject
|
||||
if (typeof rawSubject === "string" && rawSubject.trim().length > 0) {
|
||||
subject = rawSubject.trim()
|
||||
}
|
||||
}
|
||||
if (reference !== null && subject !== null) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return { id: linkedId, reference, subject }
|
||||
}, [ticket.resolvedWithTicketId, ticket.timeline])
|
||||
const [queueSelection, setQueueSelection] = useState(currentQueueName)
|
||||
const queueDirty = useMemo(() => queueSelection !== currentQueueName, [queueSelection, currentQueueName])
|
||||
const currentRequesterRecord = useMemo(
|
||||
|
|
@ -1152,6 +1186,23 @@ export function TicketSummaryHeader({ ticket }: TicketHeaderProps) {
|
|||
) : null}
|
||||
{canReopenTicket && reopenDeadlineLabel ? (
|
||||
<p className="text-xs text-neutral-500">Prazo para reabrir: {reopenDeadlineLabel}</p>
|
||||
) : null}
|
||||
{resolvedWithSummary ? (
|
||||
<Link
|
||||
href={`/tickets/${resolvedWithSummary.id}`}
|
||||
className="flex items-center gap-3 rounded-2xl border border-primary/20 bg-primary/5 px-4 py-3 text-sm font-semibold text-primary-700 transition hover:border-primary hover:bg-primary/10 hover:text-primary-800"
|
||||
>
|
||||
<span className="flex size-9 items-center justify-center rounded-full border border-primary/30 bg-white text-primary">
|
||||
<IconLink className="size-5" strokeWidth={1.7} />
|
||||
</span>
|
||||
<span className="flex flex-col">
|
||||
<span className="text-xs font-semibold uppercase tracking-wide text-primary/70">Chamado vinculado</span>
|
||||
<span className="text-sm font-semibold text-neutral-900">
|
||||
{resolvedWithSummary.reference ? `#${resolvedWithSummary.reference}` : "Ver ticket"}
|
||||
{resolvedWithSummary.subject ? ` · ${resolvedWithSummary.subject}` : ""}
|
||||
</span>
|
||||
</span>
|
||||
</Link>
|
||||
) : null}
|
||||
{isPlaying ? (
|
||||
<Tooltip>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue