feat: adiciona SLA por empresa e modal de exclusao de automacoes
Some checks failed
Some checks failed
## SLA por Empresa - Adiciona tabela companySlaSettings no schema - Cria convex/companySlas.ts com queries e mutations - Modifica resolveTicketSlaSnapshot para verificar SLA da empresa primeiro - Fallback: empresa > categoria > padrao ## Modal de Exclusao de Automacoes - Substitui confirm() nativo por Dialog gracioso - Segue padrao do delete-ticket-dialog 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b3fcbcc682
commit
33f0cc2e13
4 changed files with 404 additions and 22 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { useMemo, useState } from "react"
|
||||
import { useMutation, useQuery } from "convex/react"
|
||||
import { History, MoreHorizontal, Pencil, Plus, Trash2 } from "lucide-react"
|
||||
import { AlertTriangle, History, MoreHorizontal, Pencil, Plus, Trash2 } from "lucide-react"
|
||||
import { toast } from "sonner"
|
||||
|
||||
import { api } from "@/convex/_generated/api"
|
||||
|
|
@ -12,7 +12,7 @@ import { DEFAULT_TENANT_ID } from "@/lib/constants"
|
|||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Dialog, DialogTrigger } from "@/components/ui/dialog"
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
|
|
@ -81,6 +81,9 @@ export function AutomationsManager() {
|
|||
const [editing, setEditing] = useState<AutomationRow | null>(null)
|
||||
const [runsOpen, setRunsOpen] = useState(false)
|
||||
const [runsAutomation, setRunsAutomation] = useState<AutomationRow | null>(null)
|
||||
const [deleteOpen, setDeleteOpen] = useState(false)
|
||||
const [deletingAutomation, setDeletingAutomation] = useState<AutomationRow | null>(null)
|
||||
const [deleteLoading, setDeleteLoading] = useState(false)
|
||||
|
||||
const list = useQuery(
|
||||
api.automations.list,
|
||||
|
|
@ -134,19 +137,27 @@ export function AutomationsManager() {
|
|||
}
|
||||
}
|
||||
|
||||
const handleDelete = async (row: AutomationRow) => {
|
||||
if (!convexUserId) return
|
||||
const ok = confirm(`Excluir a automação "${row.name}"?`)
|
||||
if (!ok) return
|
||||
const handleDeleteClick = (row: AutomationRow) => {
|
||||
setDeletingAutomation(row)
|
||||
setDeleteOpen(true)
|
||||
}
|
||||
|
||||
const handleDeleteConfirm = async () => {
|
||||
if (!convexUserId || !deletingAutomation) return
|
||||
setDeleteLoading(true)
|
||||
try {
|
||||
await removeAutomation({
|
||||
tenantId,
|
||||
viewerId: convexUserId as Id<"users">,
|
||||
automationId: row.id,
|
||||
automationId: deletingAutomation.id,
|
||||
})
|
||||
toast.success("Automação excluída")
|
||||
setDeleteOpen(false)
|
||||
setDeletingAutomation(null)
|
||||
} catch (error) {
|
||||
toast.error(error instanceof Error ? error.message : "Falha ao excluir automação")
|
||||
} finally {
|
||||
setDeleteLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +351,7 @@ export function AutomationsManager() {
|
|||
<Pencil className="size-4" />
|
||||
Editar
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem variant="destructive" onClick={() => handleDelete(row)} className="gap-2">
|
||||
<DropdownMenuItem variant="destructive" onClick={() => handleDeleteClick(row)} className="gap-2">
|
||||
<Trash2 className="size-4" />
|
||||
Excluir
|
||||
</DropdownMenuItem>
|
||||
|
|
@ -355,6 +366,31 @@ export function AutomationsManager() {
|
|||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
|
||||
{/* Modal de confirmação de exclusão */}
|
||||
<Dialog open={deleteOpen} onOpenChange={(open) => {
|
||||
setDeleteOpen(open)
|
||||
if (!open) setDeletingAutomation(null)
|
||||
}}>
|
||||
<DialogContent className="max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2 text-destructive">
|
||||
<AlertTriangle className="size-5" /> Excluir automação
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Esta ação é permanente e removerá a automação <span className="font-semibold text-neutral-700">"{deletingAutomation?.name}"</span> e todo o seu histórico de execuções.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex justify-end gap-2 pt-2">
|
||||
<Button variant="outline" onClick={() => setDeleteOpen(false)} disabled={deleteLoading}>
|
||||
Cancelar
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={handleDeleteConfirm} disabled={deleteLoading} className="gap-2">
|
||||
{deleteLoading ? "Excluindo..." : (<><Trash2 className="size-4" /> Excluir</>)}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue