127 lines
6.3 KiB
TypeScript
Executable File
127 lines
6.3 KiB
TypeScript
Executable File
/**
|
|
* AddImapAccountForm.tsx
|
|
*
|
|
* @author Descomplicar® Crescimento Digital
|
|
* @link https://descomplicar.pt
|
|
* @copyright 2025 Descomplicar®
|
|
*/
|
|
|
|
import React, { useState } from 'react';
|
|
import Spinner from './Spinner'; // Certifique-se que este componente exista
|
|
|
|
interface AddImapAccountFormProps {
|
|
onConnect: (email: string, user: string, host: string, port: number, secure: boolean) => void;
|
|
onBack: () => void;
|
|
}
|
|
|
|
const AddImapAccountForm: React.FC<AddImapAccountFormProps> = ({ onConnect, onBack }) => {
|
|
const [email, setEmail] = useState('');
|
|
const [user, setUser] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [host, setHost] = useState('');
|
|
const [port, setPort] = useState(993);
|
|
const [secure, setSecure] = useState(true);
|
|
|
|
const [testStatus, setTestStatus] = useState<'idle' | 'testing' | 'success' | 'error'>('idle');
|
|
const [testMessage, setTestMessage] = useState('');
|
|
|
|
const handleTestConnection = async () => {
|
|
setTestStatus('testing');
|
|
setTestMessage('');
|
|
|
|
// A API que criamos espera um corpo de requisição (body).
|
|
// Como estamos em um ambiente de desenvolvimento sem um servidor Node rodando,
|
|
// não podemos chamar a API diretamente. A lógica abaixo é como o frontend
|
|
// se comportaria se estivesse fazendo um fetch para /api/test-imap.
|
|
// Por enquanto, vamos simular a chamada e focar na UI.
|
|
|
|
try {
|
|
const response = await fetch('/api/test-imap', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ host, port, user, password, secure })
|
|
});
|
|
|
|
if (!response.ok) {
|
|
// Tenta extrair uma mensagem de erro amigável do corpo da resposta
|
|
const errorResult = await response.json().catch(() => null);
|
|
throw new Error(errorResult?.message || `Erro no servidor: ${response.statusText}`);
|
|
}
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
setTestStatus('success');
|
|
setTestMessage(result.message);
|
|
} else {
|
|
setTestStatus('error');
|
|
setTestMessage(result.message || 'Ocorreu um erro desconhecido.');
|
|
}
|
|
} catch (error) {
|
|
setTestStatus('error');
|
|
setTestMessage(error instanceof Error ? error.message : 'Falha ao se comunicar com o servidor de teste.');
|
|
}
|
|
};
|
|
|
|
const handleSubmit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
if (testStatus === 'success') {
|
|
onConnect(email, user, host, port, secure);
|
|
} else {
|
|
alert('Por favor, teste a conexão com sucesso antes de adicionar a conta.');
|
|
}
|
|
};
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
{/* Campos do formulário... */}
|
|
<div>
|
|
<label htmlFor="email" className="block text-sm font-medium text-slate-700 dark:text-slate-300">Endereço de E-mail (para exibição)</label>
|
|
<input type="email" id="email" value={email} onChange={(e) => setEmail(e.target.value)} required className="mt-1 block w-full input" placeholder="seunome@dominio.com" />
|
|
</div>
|
|
<div>
|
|
<label htmlFor="user" className="block text-sm font-medium text-slate-700 dark:text-slate-300">Nome de Usuário (para login)</label>
|
|
<input type="text" id="user" value={user} onChange={(e) => setUser(e.target.value)} required className="mt-1 block w-full input" placeholder="geralmente o mesmo que o e-mail" />
|
|
</div>
|
|
<div>
|
|
<label htmlFor="password" className="block text-sm font-medium text-slate-700 dark:text-slate-300">Senha</label>
|
|
<input type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} required className="mt-1 block w-full input" />
|
|
</div>
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div className="col-span-2">
|
|
<label htmlFor="host" className="block text-sm font-medium text-slate-700 dark:text-slate-300">Servidor IMAP</label>
|
|
<input type="text" id="host" value={host} onChange={(e) => setHost(e.target.value)} required className="mt-1 block w-full input" placeholder="imap.dominio.com" />
|
|
</div>
|
|
<div>
|
|
<label htmlFor="port" className="block text-sm font-medium text-slate-700 dark:text-slate-300">Porta</label>
|
|
<input type="number" id="port" value={port} onChange={(e) => setPort(parseInt(e.target.value))} required className="mt-1 block w-full input" />
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center">
|
|
<input type="checkbox" id="secure" checked={secure} onChange={(e) => setSecure(e.target.checked)} className="h-4 w-4 rounded border-slate-300 text-sky-600 focus:ring-sky-500" />
|
|
<label htmlFor="secure" className="ml-2 block text-sm text-slate-900 dark:text-slate-300">Usar conexão segura (SSL/TLS)</label>
|
|
</div>
|
|
|
|
{testMessage && (
|
|
<div className={`text-sm p-3 rounded-md ${testStatus === 'success' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}`}>
|
|
{testMessage}
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex items-center justify-between gap-3 pt-2">
|
|
<button type="button" onClick={onBack} className="btn-secondary">Voltar</button>
|
|
<div className="flex items-center gap-3">
|
|
<button type="button" onClick={handleTestConnection} disabled={testStatus === 'testing'} className="btn-secondary flex items-center gap-2">
|
|
{testStatus === 'testing' && <Spinner className="w-4 h-4" />}
|
|
{testStatus === 'testing' ? 'Testando...' : 'Testar Conexão'}
|
|
</button>
|
|
<button type="submit" disabled={testStatus !== 'success'} className="btn-primary disabled:opacity-50 disabled:cursor-not-allowed">
|
|
Adicionar Conta
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
);
|
|
};
|
|
|
|
export default AddImapAccountForm; |