52 lines
2.4 KiB
TypeScript
52 lines
2.4 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { api, API_URL, SettingsStatus } from "@/lib/api";
|
|
import { Shell } from "@/components/Shell";
|
|
import { Card } from "@/components/ui";
|
|
|
|
export default function SettingsPage() {
|
|
const [settings, setSettings] = useState<SettingsStatus | null>(null);
|
|
const [apiOk, setApiOk] = useState(false);
|
|
const [error, setError] = useState("");
|
|
|
|
useEffect(() => {
|
|
Promise.all([api.health(), api.settings()]).then(([, status]) => {
|
|
setApiOk(true); setSettings(status);
|
|
}).catch((err) => setError(err.message));
|
|
}, []);
|
|
|
|
return (
|
|
<Shell>
|
|
<h1 className="text-4xl font-bold">Configuracion</h1>
|
|
<div className="mt-6 grid gap-4 lg:grid-cols-2">
|
|
<Card>
|
|
<h2 className="text-xl font-semibold">Estado</h2>
|
|
<div className="mt-4 space-y-3 text-sm">
|
|
<Row label="API" value={apiOk ? "Activa" : "No disponible"} ok={apiOk} />
|
|
<Row label="Deepgram" value={settings?.deepgram_configured ? "Configurado" : "Falta DEEPGRAM_API_KEY"} ok={!!settings?.deepgram_configured} />
|
|
<Row label="Mistral" value={settings?.mistral_configured ? "Configurado" : "Falta MISTRAL_API_KEY"} ok={!!settings?.mistral_configured} />
|
|
</div>
|
|
{error && <p className="mt-4 text-sm text-red-300">{error}</p>}
|
|
</Card>
|
|
<Card>
|
|
<h2 className="text-xl font-semibold">Rutas</h2>
|
|
<div className="mt-4 space-y-3 text-sm text-slate-300">
|
|
<p><span className="text-slate-500">API:</span> {API_URL}</p>
|
|
<p><span className="text-slate-500">Datos:</span> {settings?.data_dir || "-"}</p>
|
|
<p><span className="text-slate-500">SQLite:</span> {settings?.database_path || "-"}</p>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
<Card className="mt-4">
|
|
<h2 className="text-xl font-semibold">API Keys</h2>
|
|
<p className="mt-3 text-slate-400">Configura las claves en el archivo <code className="rounded bg-slate-900 px-2 py-1">.env</code>. No se muestran ni editan desde la UI para evitar pegarlas accidentalmente en capturas o commits.</p>
|
|
</Card>
|
|
</Shell>
|
|
);
|
|
}
|
|
|
|
function Row({ label, value, ok }: { label: string; value: string; ok: boolean }) {
|
|
return <div className="flex justify-between gap-4"><span>{label}</span><span className={ok ? "text-emerald-300" : "text-amber-300"}>{value}</span></div>;
|
|
}
|