"use client";
import { useState, useCallback } from "react";
import { Save, Eye, EyeOff, CheckCircle, AlertCircle, Loader2, RefreshCw, Sun, Moon, RotateCcw } from "lucide-react";
import { useTheme } from "next-themes";
import { useGridStore } from "@/features/grid/store/use-grid-store";
import { useScoreSettingsStore } from "@/features/score/store/use-score-settings-store";
import { useDbSettingsStore } from "@/features/settings/store/use-db-settings-store";
import { testDatabaseConnection, saveDatabaseSettings, getSavedDatabaseConfig } from "@/features/settings/actions";
import { useEffect } from "react";
import { UserManagement } from "@/features/admin/components/user-management";
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";
interface OpenRouterModel { id: string; name: string; free: boolean; }
function Section({ title, subtitle, children }: { title: string; subtitle?: string; children: React.ReactNode }) {
return (
{title}
{subtitle &&
{subtitle}
}
{children}
);
}
function Field({ label, hint, children }: { label: string; hint?: string; children: React.ReactNode }) {
return (
{children}
{hint &&
{hint}
}
);
}
export default function SettingsPage() {
const { resolvedTheme, setTheme } = useTheme();
const isDark = resolvedTheme === "dark";
const displayDensity = useGridStore((s) => s.displayDensity);
const setDisplayDensity = useGridStore((s) => s.setDisplayDensity);
const seuilAxeFort = useScoreSettingsStore((s) => s.seuilAxeFort);
const bonusParAxe = useScoreSettingsStore((s) => s.bonusParAxe);
const setSeuilAxeFort = useScoreSettingsStore((s) => s.setSeuilAxeFort);
const setBonusParAxe = useScoreSettingsStore((s) => s.setBonusParAxe);
const resetScoreDefaults = useScoreSettingsStore((s) => s.resetDefaults);
const [showKey, setShowKey] = useState(false);
const [apiKey, setApiKey] = useState("");
const [dbStatus, setDbStatus] = useState<"idle" | "testing" | "ok" | "error">("idle");
const [dbError, setDbError] = useState(null);
const [saveStatus, setSaveStatus] = useState<"idle" | "saving" | "saved">("idle");
const [models, setModels] = useState([]);
const [selectedModel, setSelectedModel] = useState("google/gemini-flash-1.5");
const [modelsStatus, setModelsStatus] = useState<"idle" | "loading" | "ok" | "error">("idle");
const [isMounted, setIsMounted] = useState(false);
const {
host, setHost,
port, setPort,
database, setDatabase,
user, setUser,
password, setPassword,
ssl, setSsl,
getDatabaseUrl
} = useDbSettingsStore();
const fetchModels = useCallback(async (key: string) => {
if (!key.trim()) return;
setModelsStatus("loading");
try {
const res = await fetch("/api/openrouter/models", { headers: { "x-openrouter-key": key } });
if (!res.ok) throw new Error();
const data = await res.json();
setModels(data.models ?? []);
setModelsStatus("ok");
} catch {
setModelsStatus("error");
}
}, []);
const reloadFromServer = useCallback(async () => {
const config = await getSavedDatabaseConfig();
if (config) {
if (config.url) {
// Parser l'URL pour remettre dans le store
try {
const url = new URL(config.url.replace("postgres://", "http://")); // URL parser helper
setHost(url.hostname);
setPort(url.port || "5432");
setDatabase(url.pathname.slice(1).split("?")[0]);
setUser(url.username);
setPassword(decodeURIComponent(url.password));
setSsl(config.url.includes("sslmode=require"));
} catch (e) {
console.error("Failed to parse saved URL", e);
}
}
if (config.openRouterKey) {
setApiKey(config.openRouterKey);
fetchModels(config.openRouterKey);
}
if (config.openRouterModel) {
setSelectedModel(config.openRouterModel);
}
}
}, [fetchModels, setApiKey, setDatabase, setHost, setPassword, setPort, setSelectedModel, setSsl, setUser]);
useEffect(() => {
setIsMounted(true);
reloadFromServer();
}, [reloadFromServer]);
const testDb = async () => {
setDbStatus("testing");
setDbError(null);
const url = getDatabaseUrl();
const res = await testDatabaseConnection(url);
if (res.success) {
setDbStatus("ok");
} else {
setDbStatus("error");
setDbError(res.error || "Erreur de connexion inconnue");
}
};
const handleSave = async () => {
setSaveStatus("saving");
const url = getDatabaseUrl();
const res = await saveDatabaseSettings(url, apiKey, selectedModel);
if (res.success) {
setSaveStatus("saved");
setTimeout(() => setSaveStatus("idle"), 2500);
} else {
setSaveStatus("idle");
alert("Erreur lors de la sauvegarde : " + res.error);
}
};
if (!isMounted) {
return null;
}
return (
Paramètres
Configuration de la connexion et des services.
{/* PostgreSQL */}
{/* OpenRouter */}
0 ? ` (${models.length} disponibles)` : ""}`}
hint={modelsStatus === "error" ? "⚠ Erreur — vérifiez votre clé puis rechargez" : modelsStatus === "idle" ? "Entrez votre clé et cliquez « Charger les modèles »" : undefined}
>
{/* Apparence */}
Thème
Interface claire ou sombre
{/* Segment control */}
Densité de la grille
Hauteur de ligne par défaut
{/* Score Produit */}
{/* Gestion des Utilisateurs */}
{/* Save */}
);
}