From 30a228e14fd06d4e3db816d85442673129060313 Mon Sep 17 00:00:00 2001 From: Yannick Le Duc Date: Mon, 25 Aug 2025 14:43:29 +0200 Subject: [PATCH] =?UTF-8?q?lien=20public=20pour=20d=C3=A9pot=20proposition?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../campaigns/[id]/propositions/page.tsx | 14 +- src/app/admin/page.tsx | 43 +++ src/app/campaigns/[id]/propose/page.tsx | 331 ++++++++++++++++++ src/components/AddPropositionModal.tsx | 69 +++- src/components/EditPropositionModal.tsx | 64 +++- src/types/index.ts | 3 + supabase-schema.sql | 3 + 7 files changed, 519 insertions(+), 8 deletions(-) create mode 100644 src/app/campaigns/[id]/propose/page.tsx 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} +
+ )} + +
+ + +
+ +
+ +