ultisuite-client/lib/mail-automation/use-automation-suggestions.ts
R3D347HR4Y 20552a34ff feat(automation): multi-domain rules and webhook scope UI
Extend automations to drive and contacts with context-aware triggers,
conditions, and actions. Webhooks can filter event types and scopes per domain.
2026-06-07 15:51:47 +02:00

141 lines
4.5 KiB
TypeScript

'use client'
import { useMemo } from 'react'
import { useQueries } from '@tanstack/react-query'
import { useAuthReady } from '@/lib/api/use-auth-ready'
import { useLabels } from '@/lib/api/hooks/use-folder-label-queries'
import { useUnifiedFolders } from '@/lib/api/hooks/use-unified-folder-queries'
import { useImapFolders } from '@/lib/api/hooks/use-imap-folders'
import { useContactBooks, fetchContactsForBook } from '@/lib/api/hooks/use-contact-queries'
import { useMailWebhooks } from '@/lib/api/hooks/use-mail-automation-queries'
import type { AutomationSuggestionKind } from '@/lib/mail-automation/condition-helpers'
export interface AutomationSuggestion {
value: string
label?: string
}
function uniqueSuggestions(items: AutomationSuggestion[]): AutomationSuggestion[] {
const seen = new Set<string>()
const out: AutomationSuggestion[] = []
for (const item of items) {
const key = item.value.trim().toLowerCase()
if (!key || seen.has(key)) continue
seen.add(key)
out.push(item)
}
return out.sort((a, b) => (a.label ?? a.value).localeCompare(b.label ?? b.value, 'fr'))
}
export function useAutomationSuggestions() {
const { ready, authenticated } = useAuthReady()
const { data: labels = [] } = useLabels()
const { data: unifiedFolders = [] } = useUnifiedFolders('all')
const { folders: imapFolders = [] } = useImapFolders()
const { data: booksRaw } = useContactBooks()
const { data: webhooks = [] } = useMailWebhooks()
const books = useMemo(() => {
if (Array.isArray(booksRaw)) return booksRaw
if (booksRaw && typeof booksRaw === 'object' && 'address_books' in booksRaw) {
return (booksRaw as { address_books: { id: string; name: string }[] }).address_books ?? []
}
return []
}, [booksRaw])
const contactQueries = useQueries({
queries: books.map((book) => ({
queryKey: ['contacts', book.id] as const,
queryFn: () => fetchContactsForBook(book.id),
enabled: ready && authenticated && !!book.id,
staleTime: 5 * 60_000,
})),
})
const labelSuggestions = useMemo(
() => uniqueSuggestions(labels.map((l) => ({ value: l.name, label: l.name }))),
[labels]
)
const folderSuggestions = useMemo(() => {
const unified = unifiedFolders.map((f) => ({ value: f.name, label: f.name }))
const imap = imapFolders.map((f) => ({
value: f.name,
label: f.remote_name !== f.name ? `${f.name} (${f.remote_name})` : f.name,
}))
return uniqueSuggestions([...unified, ...imap])
}, [unifiedFolders, imapFolders])
const folderIdSuggestions = useMemo(
() =>
uniqueSuggestions(
unifiedFolders.map((f) => ({
value: f.id,
label: `${f.name}${f.scope === 'account' ? ' · compte' : ''}`,
}))
),
[unifiedFolders]
)
const emailSuggestions = useMemo(() => {
const contacts = contactQueries.flatMap((q) => q.data ?? [])
const items: AutomationSuggestion[] = []
for (const c of contacts) {
if (c.email?.trim()) {
items.push({
value: c.email.trim(),
label: c.full_name ? `${c.full_name} <${c.email}>` : c.email,
})
}
}
return uniqueSuggestions(items)
}, [contactQueries])
const webhookSuggestions = useMemo(
() => uniqueSuggestions(webhooks.map((w) => ({ value: w.id, label: w.name }))),
[webhooks]
)
function suggestionsFor(kind: AutomationSuggestionKind): AutomationSuggestion[] {
switch (kind) {
case 'label':
return labelSuggestions
case 'folder':
return folderSuggestions
case 'folder_id':
return folderIdSuggestions
case 'email':
return emailSuggestions
case 'webhook':
return webhookSuggestions
case 'drive_path':
return [
{ value: '/', label: 'Racine Drive' },
{ value: '/Documents', label: 'Documents' },
{ value: '/Photos', label: 'Photos' },
]
case 'mime_type':
return [
{ value: 'application/pdf', label: 'PDF' },
{ value: 'image/jpeg', label: 'JPEG' },
{ value: 'image/png', label: 'PNG' },
{ value: 'text/plain', label: 'Texte' },
{ value: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', label: 'Word' },
]
case 'contact_label':
return labelSuggestions
default:
return []
}
}
return {
suggestionsFor,
labelSuggestions,
folderSuggestions,
folderIdSuggestions,
emailSuggestions,
webhookSuggestions,
}
}