sistema-de-chamados/src/components/tickets/status-select.tsx

111 lines
4.1 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import type { Id } from "@/convex/_generated/dataModel"
import type { TicketStatus } from "@/lib/schemas/ticket"
import { useAuth } from "@/lib/auth-client"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
import { CheckCircle2 } from "lucide-react"
import { CloseTicketDialog } from "@/components/tickets/close-ticket-dialog"
import { cn } from "@/lib/utils"
type StatusKey = TicketStatus | "NEW" | "OPEN" | "ON_HOLD";
const statusStyles: Record<StatusKey, { label: string; badgeClass: string }> = {
PENDING: { label: "Pendente", badgeClass: "bg-slate-100 text-slate-700" },
AWAITING_ATTENDANCE: { label: "Em andamento", badgeClass: "bg-[#dff1fb] text-[#0a4760]" },
PAUSED: { label: "Pausado", badgeClass: "bg-[#fff3c4] text-[#7a5901]" },
RESOLVED: { label: "Resolvido", badgeClass: "bg-[#dcf4eb] text-[#1f6a45]" },
NEW: { label: "Pendente", badgeClass: "bg-slate-100 text-slate-700" },
OPEN: { label: "Em andamento", badgeClass: "bg-[#dff1fb] text-[#0a4760]" },
ON_HOLD: { label: "Pausado", badgeClass: "bg-[#fff3c4] text-[#7a5901]" },
};
const baseBadgeClass =
"inline-flex h-9 items-center gap-2 rounded-full border border-slate-200 px-3 text-sm font-semibold transition hover:border-slate-300"
export function StatusSelect({
ticketId,
value,
tenantId,
requesterName,
ticketReference,
showCloseButton = true,
onStatusChange,
}: {
ticketId: string
value: TicketStatus
tenantId: string
requesterName?: string | null
ticketReference?: number | null
showCloseButton?: boolean
onStatusChange?: (next: TicketStatus) => void
}) {
const { convexUserId, session, machineContext } = useAuth()
const actorId = (convexUserId ?? null) as Id<"users"> | null
const sessionName = session?.user?.name?.trim()
const machineAssignedName = machineContext?.assignedUserName?.trim()
const agentName =
sessionName && sessionName.length > 0
? sessionName
: machineAssignedName && machineAssignedName.length > 0
? machineAssignedName
: null
const [status, setStatus] = useState<TicketStatus>(value)
const [closeDialogOpen, setCloseDialogOpen] = useState(false)
useEffect(() => {
setStatus(value)
}, [value])
return (
<>
<div className="inline-flex items-center gap-2">
<Badge className={cn(baseBadgeClass, statusStyles[status]?.badgeClass ?? statusStyles.PENDING.badgeClass)}>
{statusStyles[status]?.label ?? statusStyles.PENDING.label}
</Badge>
{showCloseButton ? (
<Tooltip>
<TooltipTrigger asChild>
<Button
type="button"
size="icon"
aria-label="Encerrar ticket"
onClick={() => setCloseDialogOpen(true)}
className="h-9 w-9 rounded-lg border border-[var(--sidebar-primary)] bg-[var(--sidebar-primary)] text-black transition hover:bg-[var(--sidebar-primary)]/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--sidebar-ring)]/30"
>
<CheckCircle2 className="size-4" />
</Button>
</TooltipTrigger>
<TooltipContent className="rounded-lg border border-slate-200 bg-white px-3 py-2 text-xs font-medium text-neutral-700 shadow-lg">
Encerrar ticket
</TooltipContent>
</Tooltip>
) : null}
</div>
{/* Dialog control visível apenas quando o botão de encerrar está presente */}
{showCloseButton ? (
<CloseTicketDialog
open={closeDialogOpen}
onOpenChange={(open) => {
if (!open) setCloseDialogOpen(false)
}}
ticketId={ticketId}
tenantId={tenantId}
actorId={actorId}
ticketReference={ticketReference ?? null}
requesterName={requesterName}
agentName={agentName}
onSuccess={() => {
setStatus("RESOLVED")
setCloseDialogOpen(false)
onStatusChange?.("RESOLVED")
}}
/>
) : null}
</>
)
}