"use client" import { useEffect, useMemo, useState } from "react" import { useMutation, useQuery } from "convex/react" import { Plus, Trash2 } from "lucide-react" import { toast } from "sonner" import { api } from "@/convex/_generated/api" import type { Id } from "@/convex/_generated/dataModel" import { useAuth } from "@/lib/auth-client" 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 { Checkbox } from "@/components/ui/checkbox" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { SearchableCombobox, type SearchableComboboxOption } from "@/components/ui/searchable-combobox" import { Switch } from "@/components/ui/switch" import { Textarea } from "@/components/ui/textarea" type ChecklistTemplateRow = { id: Id<"ticketChecklistTemplates"> name: string description: string company: { id: Id<"companies">; name: string } | null items: Array<{ id: string; text: string; required: boolean }> isArchived: boolean updatedAt: number } type CompanyRow = { id: Id<"companies">; name: string } type DraftItem = { id: string; text: string; required: boolean } const NO_COMPANY_VALUE = "__global__" function normalizeTemplateItems(items: DraftItem[]) { const normalized = items .map((item) => ({ ...item, text: item.text.trim() })) .filter((item) => item.text.length > 0) if (normalized.length === 0) { throw new Error("Adicione pelo menos um item no checklist.") } const invalid = normalized.find((item) => item.text.length > 240) if (invalid) { throw new Error("Item do checklist muito longo (máx. 240 caracteres).") } return normalized } function TemplateEditorDialog({ open, onOpenChange, template, companies, }: { open: boolean onOpenChange: (open: boolean) => void template: ChecklistTemplateRow | null companies: CompanyRow[] }) { const { convexUserId, session } = useAuth() const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID const actorId = convexUserId as Id<"users"> | null const createTemplate = useMutation(api.checklistTemplates.create) const updateTemplate = useMutation(api.checklistTemplates.update) const [saving, setSaving] = useState(false) const [name, setName] = useState("") const [description, setDescription] = useState("") const [companyValue, setCompanyValue] = useState(NO_COMPANY_VALUE) const [items, setItems] = useState([{ id: crypto.randomUUID(), text: "", required: true }]) const [archived, setArchived] = useState(false) const companyComboboxOptions = useMemo(() => { const sortedCompanies = [...companies].sort((a, b) => a.name.localeCompare(b.name, "pt-BR")) return [ { value: NO_COMPANY_VALUE, label: "Global (todas)" }, ...sortedCompanies.map((company) => ({ value: String(company.id), label: company.name })), ] }, [companies]) useEffect(() => { if (!open) return setName(template?.name ?? "") setDescription(template?.description ?? "") setCompanyValue(template?.company?.id ? String(template.company.id) : NO_COMPANY_VALUE) setItems( template?.items?.length ? template.items.map((item) => ({ id: item.id, text: item.text, required: item.required })) : [{ id: crypto.randomUUID(), text: "", required: true }] ) setArchived(template?.isArchived ?? false) }, [open, template]) const handleSave = async () => { if (!actorId) return const trimmedName = name.trim() if (trimmedName.length < 3) { toast.error("Informe um nome com pelo menos 3 caracteres.") return } let normalizedItems: DraftItem[] try { normalizedItems = normalizeTemplateItems(items) } catch (error) { toast.error(error instanceof Error ? error.message : "Itens do checklist inválidos.") return } const payload = { tenantId, actorId, name: trimmedName, description: description.trim().length > 0 ? description.trim() : undefined, companyId: companyValue !== NO_COMPANY_VALUE ? (companyValue as Id<"companies">) : undefined, items: normalizedItems.map((item) => ({ id: item.id, text: item.text, required: item.required })), isArchived: archived, } setSaving(true) try { if (template) { await updateTemplate({ templateId: template.id, ...payload }) toast.success("Template atualizado.") } else { await createTemplate(payload) toast.success("Template criado.") } onOpenChange(false) } catch (error) { toast.error(error instanceof Error ? error.message : "Falha ao salvar template.") } finally { setSaving(false) } } const canSave = Boolean(actorId) && !saving return ( {template ? "Editar template de checklist" : "Novo template de checklist"}
setName(e.target.value)} placeholder="Ex.: Checklist de instalação" />
setCompanyValue(nextValue ?? NO_COMPANY_VALUE)} options={companyComboboxOptions} placeholder="Selecionar empresa" searchPlaceholder="Buscar empresa..." triggerClassName="h-9 rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm font-medium text-neutral-800 shadow-sm" contentClassName="rounded-xl" />