ajout envoi smtp (paramètres, test envois, envoi à 1 participant). protège vue mot de passe

- ajout filtre page statistiques
This commit is contained in:
Yannick Le Duc
2025-08-25 18:28:14 +02:00
parent caed358661
commit b0a945f07b
21 changed files with 3523 additions and 30 deletions

View File

@@ -0,0 +1,181 @@
'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 SmtpSettingsForm from '@/components/SmtpSettingsForm';
import { Settings, Monitor, Save, CheckCircle, Mail } from 'lucide-react';
export const dynamic = 'force-dynamic';
function SettingsPageContent() {
const [settings, setSettings] = useState<Setting[]>([]);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [saved, setSaved] = useState(false);
const [randomizePropositions, setRandomizePropositions] = useState(false);
useEffect(() => {
loadSettings();
}, []);
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', false);
setRandomizePropositions(randomizeValue);
} catch (error) {
console.error('Erreur lors du chargement des paramètres:', error);
} finally {
setLoading(false);
}
};
const handleRandomizeChange = async (checked: boolean) => {
setRandomizePropositions(checked);
};
const handleSave = async () => {
try {
setSaving(true);
await settingsService.setBooleanValue('randomize_propositions', randomizePropositions);
setSaved(true);
setTimeout(() => setSaved(false), 2000);
} catch (error) {
console.error('Erreur lors de la sauvegarde des paramètres:', error);
} finally {
setSaving(false);
}
};
if (loading) {
return (
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
<div className="container mx-auto px-4 py-8">
<Navigation />
<div className="flex items-center justify-center h-64">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-slate-900 dark:border-slate-100 mx-auto mb-4"></div>
<p className="text-slate-600 dark:text-slate-300">Chargement des paramètres...</p>
</div>
</div>
</div>
</div>
);
}
return (
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
<div className="container mx-auto px-4 py-8">
<Navigation />
{/* Header */}
<div className="mb-8">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<div>
<h1 className="text-3xl font-bold text-slate-900 dark:text-slate-100">Paramètres</h1>
<p className="text-slate-600 dark:text-slate-300 mt-2">Configurez les paramètres de l'application</p>
</div>
<Button
onClick={handleSave}
disabled={saving}
className="flex items-center gap-2"
>
{saving ? (
<>
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
Sauvegarde...
</>
) : saved ? (
<>
<CheckCircle className="w-4 h-4" />
Sauvegardé
</>
) : (
<>
<Save className="w-4 h-4" />
Sauvegarder
</>
)}
</Button>
</div>
</div>
{/* Settings Categories */}
<div className="space-y-8">
{/* Affichage Category */}
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-blue-100 dark:bg-blue-900 rounded-lg flex items-center justify-center">
<Monitor className="w-5 h-5 text-blue-600 dark:text-blue-300" />
</div>
<div>
<CardTitle className="text-xl">Affichage</CardTitle>
<CardDescription>
Paramètres d'affichage de l'interface utilisateur
</CardDescription>
</div>
</div>
</CardHeader>
<CardContent className="space-y-6">
{/* Randomize Propositions Setting */}
<div className="flex items-center justify-between p-4 bg-slate-50 dark:bg-slate-800 rounded-lg">
<div className="flex-1">
<Label htmlFor="randomize-propositions" className="text-base font-medium">
Afficher les propositions dans un ordre aléatoire lors du vote
</Label>
<p className="text-sm text-slate-600 dark:text-slate-300 mt-1">
Lorsque activé, les propositions seront affichées dans un ordre aléatoire pour chaque participant lors du vote.
</p>
</div>
<Switch
id="randomize-propositions"
checked={randomizePropositions}
onCheckedChange={handleRandomizeChange}
className="ml-4"
/>
</div>
</CardContent>
</Card>
{/* Email Category */}
<SmtpSettingsForm onSave={() => {
setSaved(true);
setTimeout(() => setSaved(false), 2000);
}} />
{/* Future Categories Placeholder */}
<Card className="border-dashed">
<CardContent className="p-8 text-center">
<Settings className="w-12 h-12 text-slate-400 mx-auto mb-4" />
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">
Plus de catégories à venir
</h3>
<p className="text-slate-600 dark:text-slate-300">
D'autres catégories de paramètres seront ajoutées prochainement.
</p>
</CardContent>
</Card>
</div>
</div>
</div>
);
}
export default function SettingsPage() {
return (
<AuthGuard>
<SettingsPageContent />
</AuthGuard>
);
}