diff --git a/src/app/admin/campaigns/[id]/propositions/page.tsx b/src/app/admin/campaigns/[id]/propositions/page.tsx index edc9fe8..67f8975 100644 --- a/src/app/admin/campaigns/[id]/propositions/page.tsx +++ b/src/app/admin/campaigns/[id]/propositions/page.tsx @@ -170,9 +170,17 @@ export default function CampaignPropositionsPage() {

{proposition.description}

-

- Créée le {new Date(proposition.created_at).toLocaleDateString('fr-FR')} -

+
+ + Auteur : {proposition.author_first_name} {proposition.author_last_name} + + + Email : {proposition.author_email} + + + Créée le : {new Date(proposition.created_at).toLocaleDateString('fr-FR')} + +
+
+ + + + )}
diff --git a/src/app/campaigns/[id]/propose/page.tsx b/src/app/campaigns/[id]/propose/page.tsx new file mode 100644 index 0000000..b77432d --- /dev/null +++ b/src/app/campaigns/[id]/propose/page.tsx @@ -0,0 +1,331 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { useParams } from 'next/navigation'; +import Link from 'next/link'; +import { Campaign } from '@/types'; +import { campaignService, propositionService } from '@/lib/services'; + +// Force dynamic rendering to avoid SSR issues with Supabase +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 [formData, setFormData] = useState({ + title: '', + description: '', + author_first_name: '', + author_last_name: '', + author_email: '' + }); + + useEffect(() => { + if (campaignId) { + loadCampaign(); + } + }, [campaignId]); + + const loadCampaign = async () => { + try { + setLoading(true); + const campaigns = await campaignService.getAll(); + const campaignData = campaigns.find(c => 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); + } 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(''); + + try { + // Créer la proposition avec les informations de l'auteur + 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: '' + }); + } 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}

+ + Retour à l'accueil + +
+
+
+ ); + } + + if (success) { + return ( +
+
+
+ + + +

Proposition soumise !

+

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

+
+ + + Retour à l'accueil + +
+
+
+
+ ); + } + + return ( +
+
+ {/* Header */} +
+
+
+ + + + + Retour à l'accueil + +

Déposer une proposition

+

+ Campagne : {campaign?.title} +

+
+
+
+ + {/* Campaign Info */} +
+

Informations sur la campagne

+
+
+

Description

+

{campaign?.description}

+
+
+

Budget par participant

+

{campaign?.budget_per_user}€

+
+
+

Paliers de dépenses

+

{campaign?.spending_tiers}

+
+
+

Statut

+ + Dépôt de propositions + +
+
+
+ + {/* Form */} +
+
+

Votre proposition

+

+ Remplissez le formulaire ci-dessous pour soumettre votre proposition. +

+
+ +
+ {error && ( +
+ {error} +
+ )} + +
+ + +
+ +
+ +