'use client'; import { useEffect, useState, useCallback } from 'react'; import { useTranslations } from 'next-intl'; import { X, Mail, Pencil, Trash2, Plus, AlertTriangle } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Button } from '@/components/ui/button'; import { ConfirmDialog } from '@/components/ui/confirm-dialog'; import { IdentityForm } from './identity-form'; import { useIdentityStore } from '@/stores/identity-store'; import { useAuthStore } from '@/stores/auth-store'; import type { Identity, EmailAddress } from '@/lib/jmap/types'; import { toast } from '@/stores/toast-store'; import { useFocusTrap } from '@/hooks/use-focus-trap'; import { useConfirmDialog } from '@/hooks/use-confirm-dialog'; interface IdentityFormData { name: string; email: string; replyTo?: EmailAddress[]; bcc?: EmailAddress[]; textSignature?: string; htmlSignature?: string; } interface IdentityManagerModalProps { isOpen: boolean; onClose: () => void; } export function IdentityManagerModal({ isOpen, onClose }: IdentityManagerModalProps) { const t = useTranslations('identities'); const tNotif = useTranslations('notifications'); const client = useAuthStore((state) => state.client); const { identities, addIdentity, updateIdentityLocal, removeIdentity } = useIdentityStore(); const [editingId, setEditingId] = useState(null); const [isCreating, setIsCreating] = useState(false); const [deletingId, setDeletingId] = useState(null); const { dialogProps: confirmDialogProps, confirm: confirmDialog } = useConfirmDialog(); // Focus trap with Escape handling const modalRef = useFocusTrap({ isActive: isOpen, onEscape: () => { if (isCreating || editingId) { setIsCreating(false); setEditingId(null); } else { onClose(); } }, restoreFocus: true, }); // Close on click outside useEffect(() => { const handleClickOutside = (e: MouseEvent) => { if (modalRef.current && !modalRef.current.contains(e.target as Node)) { onClose(); } }; if (isOpen) { document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); } }, [isOpen, onClose, modalRef]); const handleCreate = useCallback(async (data: IdentityFormData) => { if (!client) return; try { const newIdentity = await client.createIdentity( data.name, data.email, data.replyTo, data.bcc, data.textSignature, data.htmlSignature ); addIdentity(newIdentity); setIsCreating(false); toast.success(tNotif('identity_created')); } catch (error) { const message = error instanceof Error ? error.message : t('validation_errors.unknown_error'); toast.error(tNotif('identity_create_failed', { error: message })); throw error; } }, [client, addIdentity, t, tNotif]); const handleUpdate = useCallback(async (identity: Identity, data: IdentityFormData) => { if (!client) return; try { await client.updateIdentity(identity.id, { name: data.name, replyTo: data.replyTo, bcc: data.bcc, textSignature: data.textSignature, htmlSignature: data.htmlSignature, }); updateIdentityLocal(identity.id, data); setEditingId(null); toast.success(tNotif('identity_updated')); } catch (error) { const message = error instanceof Error ? error.message : t('validation_errors.unknown_error'); toast.error(tNotif('identity_update_failed', { error: message })); throw error; } }, [client, updateIdentityLocal, t, tNotif]); const handleDelete = useCallback(async (identity: Identity) => { if (!client) return; if (!identity.mayDelete) { toast.error(t('cannot_delete')); return; } const confirmed = await confirmDialog({ title: t('delete_confirm_title'), message: t('delete_confirm'), confirmText: t('delete_button'), variant: "destructive", }); if (!confirmed) return; setDeletingId(identity.id); try { await client.deleteIdentity(identity.id); removeIdentity(identity.id); toast.success(tNotif('identity_deleted')); } catch (error) { const message = error instanceof Error ? error.message : t('validation_errors.unknown_error'); toast.error(tNotif('identity_delete_failed', { error: message })); } finally { setDeletingId(null); } }, [client, removeIdentity, t, tNotif, confirmDialog]); if (!isOpen) return null; return (
{/* Header */}

{t('modal_title')}

{/* Content */}
{/* Create New Form */} {isCreating && (

{t('create_new')}

setIsCreating(false)} />
)} {/* Create Button */} {!isCreating && !editingId && ( )} {/* Identities List */}
{identities.map((identity) => (
{editingId === identity.id ? (

{t('edit_identity')}

handleUpdate(identity, data)} onCancel={() => setEditingId(null)} />
) : (

{identity.name}

{identities[0]?.id === identity.id && ( {t('primary_identity')} )}

{identity.email}

{/* Additional Info */}
{identity.replyTo && identity.replyTo.length > 0 && (

{t('display.reply_to')} {identity.replyTo.map((a) => a.email).join(', ')}

)} {identity.bcc && identity.bcc.length > 0 && (

{t('display.bcc')} {identity.bcc.map((a) => a.email).join(', ')}

)} {identity.textSignature && (

{t('display.signature')} {identity.textSignature}

)}
{/* Actions */}
{!identity.mayDelete && (

{t('cannot_delete')}

)}
)}
))} {identities.length === 0 && !isCreating && (

{t('no_identities')}

)}
); }