869094c622
Componente reutilizable PasswordInput (icono de ojo) usado en login, registro, restablecer clave, cambiar clave, crear usuario y la clave SMTP de Configuracion, para que el usuario pueda verificar que la esta escribiendo correctamente. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
92 lines
4.0 KiB
React
92 lines
4.0 KiB
React
import { useEffect, useState } from 'react';
|
|
import { Save, Send } from 'lucide-react';
|
|
import { useUi } from '../../context/ui-context.jsx';
|
|
import { useAsync, useAction } from '../../hooks/useAsync.js';
|
|
import { getSmtpConfig, updateSmtpConfig, testSmtpConfig } from '../../services/settings.js';
|
|
import { Field, FieldRow } from '../../components/Field.jsx';
|
|
import { Button } from '../../components/Button.jsx';
|
|
import { InfoBar } from '../../components/InfoBar.jsx';
|
|
import { PasswordInput } from '../../components/PasswordInput.jsx';
|
|
|
|
export default function SmtpSettingsPanel() {
|
|
const { t, pushToast } = useUi();
|
|
const runAction = useAction();
|
|
const { data: config, reload } = useAsync(getSmtpConfig, []);
|
|
const [form, setForm] = useState({ host: '', port: 587, user: '', from: '', pass: '' });
|
|
const [testTo, setTestTo] = useState('');
|
|
const [testing, setTesting] = useState(false);
|
|
const [testResult, setTestResult] = useState(null); // { ok: bool, message: string }
|
|
|
|
useEffect(() => {
|
|
if (config) setForm({ host: config.host, port: config.port, user: config.user, from: config.from, pass: '' });
|
|
}, [config]);
|
|
|
|
async function save() {
|
|
await runAction(async () => {
|
|
await updateSmtpConfig(form);
|
|
await reload();
|
|
setForm((f) => ({ ...f, pass: '' }));
|
|
pushToast({ tone: 'success', message: t('common_saved') });
|
|
});
|
|
}
|
|
|
|
async function sendTest() {
|
|
setTestResult(null);
|
|
setTesting(true);
|
|
try {
|
|
await testSmtpConfig({ ...form, to: testTo });
|
|
setTestResult({ ok: true, message: `${t('smtp_test_success')} ${testTo}` });
|
|
} catch (err) {
|
|
setTestResult({ ok: false, message: err.message });
|
|
} finally {
|
|
setTesting(false);
|
|
}
|
|
}
|
|
|
|
if (!config) return <div className="text-muted">{t('common_loading')}</div>;
|
|
|
|
const canTest = form.host && form.user && testTo && !testing;
|
|
|
|
return (
|
|
<div>
|
|
{!config.configured && <InfoBar tone="warning" dismissible={false}>{t('smtp_not_configured')}</InfoBar>}
|
|
<FieldRow>
|
|
<Field label={t('smtp_host')}>
|
|
<input className="input" value={form.host} onChange={(e) => setForm((f) => ({ ...f, host: e.target.value }))} placeholder="192.168.222.10" />
|
|
</Field>
|
|
<Field label={t('smtp_port')}>
|
|
<input className="input" type="number" value={form.port} onChange={(e) => setForm((f) => ({ ...f, port: Number(e.target.value) }))} />
|
|
</Field>
|
|
</FieldRow>
|
|
<FieldRow>
|
|
<Field label={t('smtp_user')}>
|
|
<input className="input" value={form.user} onChange={(e) => setForm((f) => ({ ...f, user: e.target.value }))} placeholder="project@linkedcorp.net" />
|
|
</Field>
|
|
<Field label={t('smtp_from')}>
|
|
<input className="input" value={form.from} onChange={(e) => setForm((f) => ({ ...f, from: e.target.value }))} placeholder="project@linkedcorp.net" />
|
|
</Field>
|
|
</FieldRow>
|
|
<Field label={t('smtp_pass')} hint={config.configured ? t('smtp_pass_configured_hint') : undefined}>
|
|
<PasswordInput value={form.pass} onChange={(e) => setForm((f) => ({ ...f, pass: e.target.value }))} />
|
|
</Field>
|
|
<Button variant="accent" icon={Save} onClick={save}>{t('common_save')}</Button>
|
|
|
|
<div className="panel-card" style={{ marginTop: 16 }}>
|
|
<h4 style={{ marginTop: 0 }}>{t('smtp_test_title')}</h4>
|
|
<div className="text-muted" style={{ fontSize: '.76rem', marginBottom: 10 }}>{t('smtp_test_hint')}</div>
|
|
<FieldRow>
|
|
<Field label={t('smtp_test_to')}>
|
|
<input className="input" type="email" value={testTo} onChange={(e) => setTestTo(e.target.value)} placeholder="tucorreo@linkedcorp.net" />
|
|
</Field>
|
|
</FieldRow>
|
|
{testResult && (
|
|
<InfoBar tone={testResult.ok ? 'success' : 'error'}>{testResult.message}</InfoBar>
|
|
)}
|
|
<Button variant="standard" icon={Send} onClick={sendTest} disabled={!canTest}>
|
|
{testing ? t('smtp_test_sending') : t('smtp_test_send')}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|