diff --git a/client/src/pages/settings.tsx b/client/src/pages/settings.tsx index 5190dca..1090e68 100644 --- a/client/src/pages/settings.tsx +++ b/client/src/pages/settings.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from "react"; -import { Settings as SettingsIcon, Bell, Key, Shield, Cloud, Brain, Image, Upload, X } from "lucide-react"; +import { Settings as SettingsIcon, Bell, Key, Shield, Cloud, Brain, Image, Upload, X, Video } from "lucide-react"; import { useQuery, useMutation } from "@tanstack/react-query"; import Sidebar from "@/components/sidebar"; import TopBar from "@/components/topbar"; @@ -25,6 +25,8 @@ export default function Settings() { const [openrouterSystemPrompt, setOpenrouterSystemPrompt] = useState("Tu es un expert en marketing des réseaux sociaux. Génère 3 variations de textes engageants pour des publications Facebook et Instagram à partir des informations produit fournies. Chaque variation doit être unique, captivante et optimisée pour l'engagement."); const [logoFile, setLogoFile] = useState(null); const [logoPreview, setLogoPreview] = useState(null); + const [ffmpegApiUrl, setFfmpegApiUrl] = useState(""); + const [ffmpegApiKey, setFfmpegApiKey] = useState(""); const { toast } = useToast(); const { data: cloudinaryConfig } = useQuery({ @@ -39,11 +41,15 @@ export default function Settings() { queryKey: ['/api/openrouter/models'], }); + const { data: ffmpegConfig } = useQuery({ + queryKey: ['/api/ffmpeg/config'], + }); + useEffect(() => { if (cloudinaryConfig) { setCloudName((cloudinaryConfig as any).cloudName || ""); setApiKey((cloudinaryConfig as any).apiKey || ""); - + // Set logo preview if exists if ((cloudinaryConfig as any).logoPublicId) { const cloudName = (cloudinaryConfig as any).cloudName; @@ -60,15 +66,22 @@ export default function Settings() { } }, [openrouterConfig]); + useEffect(() => { + if (ffmpegConfig) { + setFfmpegApiUrl((ffmpegConfig as any).apiUrl || ""); + } + }, [ffmpegConfig]); + // Vérifier si une config OpenRouter existe déjà const hasExistingConfig = !!openrouterConfig; + const hasExistingFfmpegConfig = !!ffmpegConfig; const saveCloudinaryMutation = useMutation({ mutationFn: () => { const payload: any = { cloudName, }; - + // N'inclure apiKey et apiSecret que s'ils ne sont pas vides if (apiKey && apiKey.trim() !== "") { payload.apiKey = apiKey; @@ -76,7 +89,7 @@ export default function Settings() { if (apiSecret && apiSecret.trim() !== "") { payload.apiSecret = apiSecret; } - + return apiRequest('POST', '/api/cloudinary/config', payload); }, onSuccess: () => { @@ -103,12 +116,12 @@ export default function Settings() { model: openrouterModel, systemPrompt: openrouterSystemPrompt, }; - + // N'inclure apiKey que s'il n'est pas vide if (openrouterApiKey && openrouterApiKey.trim() !== "") { payload.apiKey = openrouterApiKey; } - + return apiRequest('POST', '/api/openrouter/config', payload); }, onSuccess: () => { @@ -132,18 +145,18 @@ export default function Settings() { mutationFn: async (file: File) => { const formData = new FormData(); formData.append('logo', file); - + const response = await fetch('/api/cloudinary/logo', { method: 'POST', credentials: 'include', body: formData, }); - + if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to upload logo'); } - + return response.json(); }, onSuccess: () => { @@ -183,6 +196,36 @@ export default function Settings() { }, }); + const saveFfmpegMutation = useMutation({ + mutationFn: () => { + const payload: any = { + apiUrl: ffmpegApiUrl, + }; + + // N'inclure apiKey que s'il n'est pas vide + if (ffmpegApiKey && ffmpegApiKey.trim() !== "") { + payload.apiKey = ffmpegApiKey; + } + + return apiRequest('POST', '/api/ffmpeg/config', payload); + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/api/ffmpeg/config'] }); + toast({ + title: "Configuration sauvegardée", + description: "Vos paramètres FFmpeg ont été enregistrés", + }); + setFfmpegApiKey(""); // Clear the API key after saving + }, + onError: () => { + toast({ + title: "Erreur", + description: "Impossible de sauvegarder la configuration FFmpeg", + variant: "destructive", + }); + }, + }); + const handleLogoChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { @@ -194,7 +237,7 @@ export default function Settings() { }); return; } - + setLogoFile(file); const reader = new FileReader(); reader.onloadend = () => { @@ -207,12 +250,12 @@ export default function Settings() { return (
{sidebarOpen && ( -
setSidebarOpen(false)} /> )} - +
setSidebarOpen(!sidebarOpen)} /> - +

Paramètres

@@ -339,11 +382,11 @@ export default function Settings() { Définissez les instructions que l'IA doit suivre pour générer vos textes

-
- + + + @@ -430,9 +533,9 @@ export default function Settings() { {logoPreview ? (
- Logo