'use client'; import { useState, useEffect } from 'react'; import { Setting } from '@/types'; import { settingsService } from '@/lib/services'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; import Navigation from '@/components/Navigation'; import AuthGuard from '@/components/AuthGuard'; import Footer from '@/components/Footer'; import SmtpSettingsForm from '@/components/SmtpSettingsForm'; import { Settings, Monitor, Save, CheckCircle, Mail, FileText, Download } from 'lucide-react'; import { ExportAnonymizationSelect, AnonymizationLevel } from '@/components/ExportAnonymizationSelect'; import { ExportFileFormatSelect, ExportFileFormat } from '@/components/ExportFileFormatSelect'; export const dynamic = 'force-dynamic'; function SettingsPageContent() { const [settings, setSettings] = useState([]); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [saved, setSaved] = useState(false); const [randomizePropositions, setRandomizePropositions] = useState(false); const [proposePageMessage, setProposePageMessage] = useState(''); const [footerMessage, setFooterMessage] = useState(''); const [exportAnonymization, setExportAnonymization] = useState('full'); const [exportFileFormat, setExportFileFormat] = useState('ods'); // États pour la détection des modifications const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); const [originalValues, setOriginalValues] = useState<{ randomizePropositions: boolean; proposePageMessage: string; footerMessage: string; exportAnonymization: AnonymizationLevel; exportFileFormat: ExportFileFormat; } | null>(null); const [autoSaved, setAutoSaved] = useState(false); useEffect(() => { // Vérifier la configuration Supabase const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL; const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; // Si pas de configuration ou valeurs par défaut, rediriger vers setup if (!supabaseUrl || !supabaseAnonKey || supabaseUrl === 'https://placeholder.supabase.co' || supabaseAnonKey === 'your-anon-key') { console.log('🔧 Configuration Supabase manquante, redirection vers /setup'); window.location.href = '/setup'; return; } loadSettings(); }, []); // Détecter les modifications useEffect(() => { if (!originalValues) return; const hasChanges = randomizePropositions !== originalValues.randomizePropositions || proposePageMessage !== originalValues.proposePageMessage || footerMessage !== originalValues.footerMessage || exportAnonymization !== originalValues.exportAnonymization || exportFileFormat !== originalValues.exportFileFormat; setHasUnsavedChanges(hasChanges); }, [randomizePropositions, proposePageMessage, footerMessage, exportAnonymization, exportFileFormat, originalValues]); // Avertissement avant de quitter la page useEffect(() => { const handleBeforeUnload = (e: BeforeUnloadEvent) => { if (hasUnsavedChanges) { e.preventDefault(); e.returnValue = 'Vous avez des modifications non sauvegardées. Êtes-vous sûr de vouloir quitter ?'; return e.returnValue; } }; window.addEventListener('beforeunload', handleBeforeUnload); return () => window.removeEventListener('beforeunload', handleBeforeUnload); }, [hasUnsavedChanges]); const loadSettings = async () => { try { setLoading(true); const settingsData = await settingsService.getAll(); setSettings(settingsData); // Charger la valeur du paramètre d'ordre aléatoire const randomizeValue = await settingsService.getBooleanValue('randomize_propositions', true); setRandomizePropositions(randomizeValue); // Charger le message de la page de dépôt de propositions const messageValue = await settingsService.getStringValue('propose_page_message', 'Partagez votre vision et proposez des projets qui feront la différence dans votre collectif. Votre voix compte pour façonner l\'avenir de votre communauté.'); setProposePageMessage(messageValue); // Charger le message du bas de page const footerValue = await settingsService.getStringValue('footer_message', 'Développé avec ❤️ pour faciliter la démocratie participative - [Logiciel libre et open source](GITURL)'); setFooterMessage(footerValue); // Charger le niveau d'anonymisation des exports const anonymizationValue = await settingsService.getStringValue('export_anonymization', 'full') as AnonymizationLevel; setExportAnonymization(anonymizationValue); // Charger le format de fichier d'export const fileFormatValue = await settingsService.getStringValue('export_file_format', 'ods') as ExportFileFormat; setExportFileFormat(fileFormatValue); // Stocker les valeurs originales pour la détection des modifications setOriginalValues({ randomizePropositions: randomizeValue, proposePageMessage: messageValue, footerMessage: footerValue, exportAnonymization: anonymizationValue, exportFileFormat: fileFormatValue }); } catch (error) { console.error('Erreur lors du chargement des paramètres:', error); } finally { setLoading(false); } }; const handleRandomizeChange = async (checked: boolean) => { setRandomizePropositions(checked); // Sauvegarde automatique pour ce paramètre try { await settingsService.setBooleanValue('randomize_propositions', checked); // Mettre à jour les valeurs originales if (originalValues) { setOriginalValues({ ...originalValues, randomizePropositions: checked }); } // Afficher la confirmation de sauvegarde automatique setAutoSaved(true); setTimeout(() => setAutoSaved(false), 2000); } catch (error) { console.error('Erreur lors de la sauvegarde automatique:', error); } }; const handleExportAnonymizationChange = async (value: AnonymizationLevel) => { setExportAnonymization(value); // Sauvegarde automatique pour ce paramètre try { await settingsService.setStringValue('export_anonymization', value); // Mettre à jour les valeurs originales if (originalValues) { setOriginalValues({ ...originalValues, exportAnonymization: value }); } // Afficher la confirmation de sauvegarde automatique setAutoSaved(true); setTimeout(() => setAutoSaved(false), 2000); } catch (error) { console.error('Erreur lors de la sauvegarde automatique:', error); } }; const handleExportFileFormatChange = async (value: ExportFileFormat) => { setExportFileFormat(value); // Sauvegarde automatique pour ce paramètre try { await settingsService.setStringValue('export_file_format', value); // Mettre à jour les valeurs originales if (originalValues) { setOriginalValues({ ...originalValues, exportFileFormat: value }); } // Afficher la confirmation de sauvegarde automatique setAutoSaved(true); setTimeout(() => setAutoSaved(false), 2000); } catch (error) { console.error('Erreur lors de la sauvegarde automatique:', error); } }; const handleSave = async () => { try { setSaving(true); // Sauvegarder seulement les paramètres qui ne sont pas sauvegardés automatiquement await settingsService.setStringValue('propose_page_message', proposePageMessage); await settingsService.setStringValue('footer_message', footerMessage); // Mettre à jour les valeurs originales setOriginalValues({ randomizePropositions, proposePageMessage, footerMessage, exportAnonymization, exportFileFormat }); setSaved(true); setTimeout(() => setSaved(false), 3000); // Message plus long pour les textes } catch (error) { console.error('Erreur lors de la sauvegarde des paramètres:', error); } finally { setSaving(false); } }; if (loading) { return (

Chargement des paramètres...

); } return (
{/* Header */}

Paramètres

{hasUnsavedChanges && (
Modifications non sauvegardées
)} {autoSaved && (
Sauvegardé automatiquement
)}

{hasUnsavedChanges ? 'Vous avez des modifications non sauvegardées. N\'oubliez pas de cliquer sur "Sauvegarder".' : 'Configurez les paramètres de l\'application' }

{/* Settings Categories */}
{/* Affichage Category */}
Affichage Paramètres d'affichage de l'interface utilisateur
{/* Randomize Propositions Setting */}

Lorsque activé, les propositions seront affichées dans un ordre aléatoire pour chaque participant lors du vote.

{/* Textes Category */}
Textes Personnalisez les textes affichés dans l'application
{/* Propose Page Message Setting */}

Ce texte apparaît sous le titre de la campagne pour inviter les utilisateurs à déposer des propositions.