/** * Template picker dropdown for compose modal. * Lists available templates and inserts selected template body into editor. */ import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { fetchTemplates, substituteTemplate, type MailTemplate } from '@/api/mail'; import { EmptyState } from '@/components/ui/EmptyState'; import { Loader2 } from 'lucide-react'; export interface TemplatePickerProps { onSelect: (body: string, subject: string) => void; } export function TemplatePicker({ onSelect }: TemplatePickerProps) { const { t } = useTranslation(); const [templates, setTemplates] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; setLoading(true); fetchTemplates() .then((data) => { if (!cancelled) { setTemplates(data); setError(null); } }) .catch((err) => { if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); } }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, []); const handleSelect = (template: MailTemplate) => { substituteTemplate({ template_id: template.id, variables: {}, }) .then((result) => { onSelect(result.body, result.subject || template.subject); }) .catch(() => { onSelect(template.body, template.subject); }); }; if (loading) { return (
); } if (error) { return (

{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}

); } if (templates.length === 0) { return ( ); } return (

{t('mail.selectTemplate')}

    {templates.map((template) => (
  • ))}
); }