Extend automations to drive and contacts with context-aware triggers, conditions, and actions. Webhooks can filter event types and scopes per domain.
135 lines
4.6 KiB
TypeScript
135 lines
4.6 KiB
TypeScript
"use client"
|
|
|
|
import { useCallback, useState } from "react"
|
|
import { Check, Copy } from "lucide-react"
|
|
import { toast } from "sonner"
|
|
import {
|
|
webhookVariableGroupsForDomains,
|
|
type WebhookTemplateVariable,
|
|
} from "@/lib/mail-automation/webhook-template-variables"
|
|
import {
|
|
AUTOMATION_DOMAIN_LABELS,
|
|
type AutomationDomain,
|
|
} from "@/lib/mail-automation/domains"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
const DOMAIN_TABS: Array<AutomationDomain | "all"> = ["all", "mail", "drive", "contacts"]
|
|
|
|
function VariableChip({
|
|
variable,
|
|
copied,
|
|
onCopy,
|
|
}: {
|
|
variable: WebhookTemplateVariable
|
|
copied: boolean
|
|
onCopy: (token: string) => void
|
|
}) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
title={`${variable.label} — ${variable.description}`}
|
|
aria-label={`Copier ${variable.token}`}
|
|
onClick={() => onCopy(variable.token)}
|
|
className={cn(
|
|
"inline-flex max-w-full items-center gap-1 rounded-md border px-2 py-0.5 font-mono text-[11px] leading-snug transition-colors",
|
|
"border-border bg-muted/40 text-foreground hover:bg-accent hover:text-accent-foreground",
|
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50",
|
|
copied && "border-primary/40 bg-primary/10 text-primary"
|
|
)}
|
|
>
|
|
{copied ? (
|
|
<Check className="size-3 shrink-0" aria-hidden />
|
|
) : (
|
|
<Copy className="size-3 shrink-0 opacity-60" aria-hidden />
|
|
)}
|
|
<span className="truncate">{variable.token}</span>
|
|
</button>
|
|
)
|
|
}
|
|
|
|
export function WebhookTemplateVariablesPanel() {
|
|
const [copiedToken, setCopiedToken] = useState<string | null>(null)
|
|
const [filter, setFilter] = useState<AutomationDomain | "all">("all")
|
|
|
|
const groups =
|
|
filter === "all"
|
|
? webhookVariableGroupsForDomains(["mail", "drive", "contacts"])
|
|
: webhookVariableGroupsForDomains([filter])
|
|
|
|
const copyToken = useCallback(async (token: string) => {
|
|
try {
|
|
await navigator.clipboard.writeText(token)
|
|
setCopiedToken(token)
|
|
toast.success(`${token} copié`)
|
|
window.setTimeout(() => {
|
|
setCopiedToken((current) => (current === token ? null : current))
|
|
}, 1500)
|
|
} catch {
|
|
toast.error("Impossible de copier la variable")
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<div className="space-y-4 rounded-lg border border-border bg-muted/20 p-4">
|
|
<div className="space-y-2">
|
|
<p className="text-sm font-medium">Variables du template</p>
|
|
<p className="text-xs text-muted-foreground">
|
|
Variables selon le type d'événement (mail, Drive, contacts). Les variables communes
|
|
($event.*, $date) fonctionnent partout.
|
|
</p>
|
|
<div className="flex flex-wrap gap-1">
|
|
{DOMAIN_TABS.map((tab) => (
|
|
<button
|
|
key={tab}
|
|
type="button"
|
|
onClick={() => setFilter(tab)}
|
|
className={cn(
|
|
"rounded-md border px-2 py-0.5 text-[11px] transition-colors",
|
|
filter === tab
|
|
? "border-primary bg-primary/10 text-primary"
|
|
: "border-border bg-background text-muted-foreground hover:bg-muted"
|
|
)}
|
|
>
|
|
{tab === "all" ? "Tout" : AUTOMATION_DOMAIN_LABELS[tab]}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
{groups.map((group) => (
|
|
<section key={group.id} className="space-y-2">
|
|
<div>
|
|
<h3 className="text-xs font-medium">{group.label}</h3>
|
|
<p className="text-[11px] text-muted-foreground">{group.description}</p>
|
|
</div>
|
|
<ul className="space-y-2">
|
|
{group.variables.map((variable) => (
|
|
<li
|
|
key={variable.token}
|
|
className="flex flex-col gap-1.5 sm:flex-row sm:items-start sm:gap-3"
|
|
>
|
|
<VariableChip
|
|
variable={variable}
|
|
copied={copiedToken === variable.token}
|
|
onCopy={copyToken}
|
|
/>
|
|
<div className="min-w-0 flex-1 text-[11px] leading-snug">
|
|
<span className="font-medium text-foreground">{variable.label}</span>
|
|
<span className="text-muted-foreground"> — {variable.description}</span>
|
|
{variable.example ? (
|
|
<span className="mt-0.5 block font-mono text-[10px] text-muted-foreground/80">
|
|
Ex. {variable.example}
|
|
</span>
|
|
) : null}
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</section>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|