'use client'; import { useState, useEffect } from 'react'; import { useParams } from 'next/navigation'; import Link from 'next/link'; import { Campaign } from '@/types'; import { campaignService, propositionService, settingsService } from '@/lib/services'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { ArrowLeft, FileText, User, Mail, CheckCircle, AlertCircle } from 'lucide-react'; import { MarkdownContent } from '@/components/MarkdownContent'; import { MarkdownEditor } from '@/components/MarkdownEditor'; import { PROJECT_CONFIG } from '@/lib/project.config'; import Footer from '@/components/Footer'; export const dynamic = 'force-dynamic'; export default function PublicProposePage() { const params = useParams(); const campaignId = params.id as string; const [campaign, setCampaign] = useState(null); const [loading, setLoading] = useState(true); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(''); const [success, setSuccess] = useState(false); const [startTime] = useState(Date.now()); // Validation temporelle const [proposePageMessage, setProposePageMessage] = useState(''); const [formData, setFormData] = useState({ title: '', description: '', author_first_name: '', author_last_name: '', author_email: '', website: '' // Honeypot field }); useEffect(() => { if (campaignId) { loadCampaign(); } }, [campaignId]); const loadCampaign = async () => { try { setLoading(true); const [campaigns, messageValue] = await Promise.all([ campaignService.getAll(), 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é.') ]); const campaignData = campaigns.find((c: Campaign) => c.id === campaignId); if (!campaignData) { setError('Campagne non trouvée'); return; } if (campaignData.status !== 'deposit') { setError('Cette campagne n\'accepte plus de propositions'); return; } setCampaign(campaignData); setProposePageMessage(messageValue); } catch (error) { console.error('Erreur lors du chargement de la campagne:', error); setError('Erreur lors du chargement de la campagne'); } finally { setLoading(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setSubmitting(true); setError(''); // Validation temporelle - détecte les soumissions trop rapides const timeSpent = Date.now() - startTime; if (timeSpent < 5000) { // Moins de 5 secondes setError('Veuillez prendre le temps de bien rédiger votre proposition'); setSubmitting(false); return; } // Validation honeypot - détecte les bots if (formData.website) { setError('Soumission invalide'); setSubmitting(false); return; } try { await propositionService.create({ campaign_id: campaignId, title: formData.title, description: formData.description, author_first_name: formData.author_first_name, author_last_name: formData.author_last_name, author_email: formData.author_email }); setSuccess(true); setFormData({ title: '', description: '', author_first_name: '', author_last_name: '', author_email: '', website: '' }); } catch (err: any) { const errorMessage = err?.message || err?.details || 'Erreur lors de la soumission de la proposition'; setError(`Erreur lors de la soumission de la proposition: ${errorMessage}`); } finally { setSubmitting(false); } }; const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; if (loading) { return (

Chargement de la campagne...

); } if (error && !campaign) { return (

Erreur

{error}

); } if (success) { return (

Proposition soumise !

Votre proposition a été soumise avec succès. Merci pour votre participation !

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

{campaign?.title}

{proposePageMessage}

{/* Campaign Description */}
{/* Form */} Votre proposition
{error && (

{error}

)} {/* Honeypot field - caché pour détecter les bots */}
setFormData(prev => ({ ...prev, description: value }))} placeholder="Décrivez votre proposition en détail..." label="Description *" maxLength={2000} />

Vos informations

{/* Footer discret */}
); }