fix(email-action): corrige cores e acentuação, adiciona drag and drop
- Badges de variáveis agora com fundo preto e texto branco - Corrige todos os textos sem acentuação (Referência, Título, etc.) - Adiciona suporte a drag and drop das badges de variáveis 🤖 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
81e4b528d3
commit
2ab6ed595c
1 changed files with 30 additions and 25 deletions
|
|
@ -46,24 +46,24 @@ type EmailActionConfigProps = {
|
||||||
agents: Agent[]
|
agents: Agent[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variaveis disponiveis para interpolacao
|
// Variáveis disponíveis para interpolação
|
||||||
const EMAIL_VARIABLES = [
|
const EMAIL_VARIABLES = [
|
||||||
{ key: "ticket.reference", label: "Referencia", description: "Numero do chamado (ex: #1234)" },
|
{ key: "ticket.reference", label: "Referência", description: "Número do chamado (ex: #1234)" },
|
||||||
{ key: "ticket.subject", label: "Assunto", description: "Titulo do chamado" },
|
{ key: "ticket.subject", label: "Assunto", description: "Título do chamado" },
|
||||||
{ key: "ticket.status", label: "Status", description: "Status atual do chamado" },
|
{ key: "ticket.status", label: "Status", description: "Status atual do chamado" },
|
||||||
{ key: "ticket.priority", label: "Prioridade", description: "Nivel de prioridade" },
|
{ key: "ticket.priority", label: "Prioridade", description: "Nível de prioridade" },
|
||||||
{ key: "company.name", label: "Empresa", description: "Nome da empresa do solicitante" },
|
{ key: "company.name", label: "Empresa", description: "Nome da empresa do solicitante" },
|
||||||
{ key: "requester.name", label: "Solicitante", description: "Nome de quem abriu o chamado" },
|
{ key: "requester.name", label: "Solicitante", description: "Nome de quem abriu o chamado" },
|
||||||
{ key: "assignee.name", label: "Responsavel", description: "Nome do agente responsavel" },
|
{ key: "assignee.name", label: "Responsável", description: "Nome do agente responsável" },
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
type EmailVariable = (typeof EMAIL_VARIABLES)[number]
|
type EmailVariable = (typeof EMAIL_VARIABLES)[number]
|
||||||
|
|
||||||
const CLEAR_SELECT_VALUE = "__clear__"
|
const CLEAR_SELECT_VALUE = "__clear__"
|
||||||
|
|
||||||
// Estilos do badge de variavel (cyan para consistencia com o projeto)
|
// Estilos do badge de variável (fundo preto com texto branco)
|
||||||
const VARIABLE_BADGE_CLASSES =
|
const VARIABLE_BADGE_CLASSES =
|
||||||
"inline-flex items-center gap-1 rounded-md bg-cyan-50/60 border border-cyan-200/60 px-1.5 py-0.5 text-xs font-mono text-cyan-700 whitespace-nowrap"
|
"inline-flex items-center gap-1 rounded-md bg-neutral-900 border border-neutral-700 px-1.5 py-0.5 text-xs font-mono text-white whitespace-nowrap"
|
||||||
|
|
||||||
// Extensao TipTap para variaveis de e-mail
|
// Extensao TipTap para variaveis de e-mail
|
||||||
const EmailVariableMentionExtension = Mention.extend({
|
const EmailVariableMentionExtension = Mention.extend({
|
||||||
|
|
@ -280,7 +280,7 @@ function EmailVariableList({ items, command, onRegister }: EmailVariableListProp
|
||||||
type="button"
|
type="button"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full flex-col gap-0.5 rounded-md px-3 py-2 text-left transition",
|
"flex w-full flex-col gap-0.5 rounded-md px-3 py-2 text-left transition",
|
||||||
index === selectedIndex ? "bg-cyan-50/60" : "hover:bg-slate-50"
|
index === selectedIndex ? "bg-neutral-100" : "hover:bg-slate-50"
|
||||||
)}
|
)}
|
||||||
onMouseEnter={() => setSelectedIndex(index)}
|
onMouseEnter={() => setSelectedIndex(index)}
|
||||||
onMouseDown={(e) => {
|
onMouseDown={(e) => {
|
||||||
|
|
@ -288,7 +288,7 @@ function EmailVariableList({ items, command, onRegister }: EmailVariableListProp
|
||||||
selectItem(index)
|
selectItem(index)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="font-mono text-sm text-cyan-700">{`{{${item.key}}}`}</span>
|
<span className="font-mono text-sm text-neutral-900">{`{{${item.key}}}`}</span>
|
||||||
<span className="text-xs text-muted-foreground">{item.description}</span>
|
<span className="text-xs text-muted-foreground">{item.description}</span>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
|
@ -440,11 +440,11 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Header com tipo e botao de remover */}
|
{/* Header com tipo e botão de remover */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="flex size-8 items-center justify-center rounded-lg bg-cyan-50/60">
|
<div className="flex size-8 items-center justify-center rounded-lg bg-neutral-900">
|
||||||
<Braces className="size-4 text-cyan-600" />
|
<Braces className="size-4 text-white" />
|
||||||
</div>
|
</div>
|
||||||
<span className="font-medium text-neutral-900">Enviar e-mail</span>
|
<span className="font-medium text-neutral-900">Enviar e-mail</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -454,7 +454,7 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={onRemove}
|
onClick={onRemove}
|
||||||
className="h-8 w-8 text-slate-500 hover:bg-red-50 hover:text-red-700"
|
className="h-8 w-8 text-slate-500 hover:bg-red-50 hover:text-red-700"
|
||||||
title="Remover acao"
|
title="Remover ação"
|
||||||
>
|
>
|
||||||
<Trash2 className="size-4" />
|
<Trash2 className="size-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -486,10 +486,10 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Paleta de variaveis */}
|
{/* Paleta de variáveis */}
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-xs text-muted-foreground">
|
<Label className="text-xs text-muted-foreground">
|
||||||
Variaveis disponiveis (clique para inserir no {activeField === "subject" ? "assunto" : "corpo"})
|
Variáveis disponíveis (arraste ou clique para inserir no {activeField === "subject" ? "assunto" : "corpo"})
|
||||||
</Label>
|
</Label>
|
||||||
<div className="flex flex-wrap gap-1.5">
|
<div className="flex flex-wrap gap-1.5">
|
||||||
{EMAIL_VARIABLES.map((variable) => (
|
{EMAIL_VARIABLES.map((variable) => (
|
||||||
|
|
@ -497,10 +497,15 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
draggable
|
||||||
onClick={() => handleInsertVariable(variable)}
|
onClick={() => handleInsertVariable(variable)}
|
||||||
|
onDragStart={(e) => {
|
||||||
|
e.dataTransfer.setData("text/plain", `{{${variable.key}}}`)
|
||||||
|
e.dataTransfer.effectAllowed = "copy"
|
||||||
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
VARIABLE_BADGE_CLASSES,
|
VARIABLE_BADGE_CLASSES,
|
||||||
"cursor-pointer transition hover:bg-cyan-100/60 hover:border-cyan-300/60"
|
"cursor-grab transition hover:bg-neutral-800 active:cursor-grabbing"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{`{{${variable.key}}}`}
|
{`{{${variable.key}}}`}
|
||||||
|
|
@ -514,9 +519,9 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Destinatarios */}
|
{/* Destinatários */}
|
||||||
<div className="space-y-3 rounded-lg border border-slate-200 bg-slate-50/50 p-4">
|
<div className="space-y-3 rounded-lg border border-slate-200 bg-slate-50/50 p-4">
|
||||||
<Label className="text-sm font-medium">Destinatarios</Label>
|
<Label className="text-sm font-medium">Destinatários</Label>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
<label className="flex items-center gap-2 text-sm text-neutral-700">
|
<label className="flex items-center gap-2 text-sm text-neutral-700">
|
||||||
|
|
@ -531,13 +536,13 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
checked={action.toAssignee}
|
checked={action.toAssignee}
|
||||||
onCheckedChange={(checked) => handleChange("toAssignee", Boolean(checked))}
|
onCheckedChange={(checked) => handleChange("toAssignee", Boolean(checked))}
|
||||||
/>
|
/>
|
||||||
Responsavel do ticket
|
Responsável do ticket
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-3 sm:grid-cols-2">
|
<div className="grid gap-3 sm:grid-cols-2">
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<Label className="text-xs text-muted-foreground">Agente especifico (opcional)</Label>
|
<Label className="text-xs text-muted-foreground">Agente específico (opcional)</Label>
|
||||||
<Select
|
<Select
|
||||||
value={action.toUserId}
|
value={action.toUserId}
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
|
|
@ -551,8 +556,8 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
<SelectContent className="rounded-xl">
|
<SelectContent className="rounded-xl">
|
||||||
{agents.length === 0 ? (
|
{agents.length === 0 ? (
|
||||||
<SelectEmptyState
|
<SelectEmptyState
|
||||||
message="Nenhum agente disponivel"
|
message="Nenhum agente disponível"
|
||||||
createLabel="Gerenciar usuarios"
|
createLabel="Gerenciar usuários"
|
||||||
createHref="/admin/users"
|
createHref="/admin/users"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -581,10 +586,10 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Botao do e-mail */}
|
{/* Botão do e-mail */}
|
||||||
<div className="grid gap-3 sm:grid-cols-2">
|
<div className="grid gap-3 sm:grid-cols-2">
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<Label className="text-xs text-muted-foreground">Link do botao</Label>
|
<Label className="text-xs text-muted-foreground">Link do botão</Label>
|
||||||
<Select
|
<Select
|
||||||
value={action.ctaTarget}
|
value={action.ctaTarget}
|
||||||
onValueChange={(value) => handleChange("ctaTarget", value as EmailCtaTarget)}
|
onValueChange={(value) => handleChange("ctaTarget", value as EmailCtaTarget)}
|
||||||
|
|
@ -601,7 +606,7 @@ export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailA
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<Label className="text-xs text-muted-foreground">Texto do botao</Label>
|
<Label className="text-xs text-muted-foreground">Texto do botão</Label>
|
||||||
<Input
|
<Input
|
||||||
value={action.ctaLabel}
|
value={action.ctaLabel}
|
||||||
onChange={(e) => handleChange("ctaLabel", e.target.value)}
|
onChange={(e) => handleChange("ctaLabel", e.target.value)}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue