- améliore l'export/import (format de fichiers en paramètres, amélioration de la robustesse, )

- ajout bouton tout effacer des propositions et participants
This commit is contained in:
Yannick Le Duc
2025-09-16 15:45:28 +02:00
parent 6aead108d7
commit 2a2738f5c0
16 changed files with 1455 additions and 81 deletions

View File

@@ -9,6 +9,7 @@ import EditParticipantModal from '@/components/EditParticipantModal';
import DeleteParticipantModal from '@/components/DeleteParticipantModal';
import ImportFileModal from '@/components/ImportFileModal';
import SendParticipantEmailModal from '@/components/SendParticipantEmailModal';
import ClearAllParticipantsModal from '@/components/ClearAllParticipantsModal';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
@@ -31,6 +32,7 @@ function CampaignParticipantsPageContent() {
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [showImportModal, setShowImportModal] = useState(false);
const [showSendEmailModal, setShowSendEmailModal] = useState(false);
const [showClearAllModal, setShowClearAllModal] = useState(false);
const [selectedParticipant, setSelectedParticipant] = useState<Participant | null>(null);
const [copiedParticipantId, setCopiedParticipantId] = useState<string | null>(null);
@@ -87,9 +89,9 @@ function CampaignParticipantsPageContent() {
try {
const participantsToCreate = data.map(row => ({
campaign_id: campaignId,
first_name: row.first_name || '',
last_name: row.last_name || '',
email: row.email || ''
first_name: row.Prénom || '',
last_name: row.Nom || '',
email: row.Email || ''
}));
// Créer les participants un par un
@@ -103,6 +105,16 @@ function CampaignParticipantsPageContent() {
}
};
const handleClearAllParticipants = async () => {
try {
await participantService.deleteAllByCampaign(campaignId);
loadData();
} catch (error) {
console.error('Erreur lors de la suppression des participants:', error);
throw error;
}
};
const getInitials = (firstName: string, lastName: string) => {
return `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase();
};
@@ -182,6 +194,16 @@ function CampaignParticipantsPageContent() {
<Upload className="w-4 h-4 mr-2" />
Importer
</Button>
{participants.length > 0 && (
<Button
variant="outline"
onClick={() => setShowClearAllModal(true)}
className="text-red-600 border-red-200 hover:bg-red-50 hover:border-red-300 dark:text-red-400 dark:border-red-800 dark:hover:bg-red-900/20"
>
<User className="w-4 h-4 mr-2" />
Tout effacer
</Button>
)}
<Button onClick={() => setShowAddModal(true)} size="lg">
Nouveau participant
</Button>
@@ -377,6 +399,14 @@ function CampaignParticipantsPageContent() {
campaign={campaign}
/>
)}
<ClearAllParticipantsModal
isOpen={showClearAllModal}
onClose={() => setShowClearAllModal(false)}
onConfirm={handleClearAllParticipants}
campaignTitle={campaign?.title}
participantCount={participants.length}
/>
</div>
</div>
);

View File

@@ -8,6 +8,8 @@ import AddPropositionModal from '@/components/AddPropositionModal';
import EditPropositionModal from '@/components/EditPropositionModal';
import DeletePropositionModal from '@/components/DeletePropositionModal';
import ImportFileModal from '@/components/ImportFileModal';
import ExportPropositionsButton from '@/components/ExportPropositionsButton';
import ClearAllPropositionsModal from '@/components/ClearAllPropositionsModal';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
@@ -29,6 +31,7 @@ function CampaignPropositionsPageContent() {
const [showEditModal, setShowEditModal] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [showImportModal, setShowImportModal] = useState(false);
const [showClearAllModal, setShowClearAllModal] = useState(false);
const [selectedProposition, setSelectedProposition] = useState<Proposition | null>(null);
useEffect(() => {
@@ -84,11 +87,11 @@ function CampaignPropositionsPageContent() {
try {
const propositionsToCreate = data.map(row => ({
campaign_id: campaignId,
title: row.title || '',
description: row.description || '',
author_first_name: row.author_first_name || 'admin',
author_last_name: row.author_last_name || 'admin',
author_email: row.author_email || 'admin@example.com'
title: row.Titre || '',
description: row.Description || '',
author_first_name: row.Prénom || 'admin',
author_last_name: row.Nom || 'admin',
author_email: row.Email || 'admin@example.com'
}));
// Créer les propositions une par une
@@ -102,7 +105,15 @@ function CampaignPropositionsPageContent() {
}
};
const handleClearAllPropositions = async () => {
try {
await propositionService.deleteAllByCampaign(campaignId);
loadData();
} catch (error) {
console.error('Erreur lors de la suppression des propositions:', error);
throw error;
}
};
const getInitials = (firstName: string, lastName: string) => {
return `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase();
@@ -171,6 +182,20 @@ function CampaignPropositionsPageContent() {
<Upload className="w-4 h-4 mr-2" />
Importer
</Button>
<ExportPropositionsButton
propositions={propositions}
campaignTitle={campaign.title}
/>
{propositions.length > 0 && (
<Button
variant="outline"
onClick={() => setShowClearAllModal(true)}
className="text-red-600 border-red-200 hover:bg-red-50 hover:border-red-300 dark:text-red-400 dark:border-red-800 dark:hover:bg-red-900/20"
>
<FileText className="w-4 h-4 mr-2" />
Tout effacer
</Button>
)}
<Button onClick={() => setShowAddModal(true)} size="lg">
Nouvelle proposition
</Button>
@@ -299,6 +324,14 @@ function CampaignPropositionsPageContent() {
type="propositions"
campaignTitle={campaign?.title}
/>
<ClearAllPropositionsModal
isOpen={showClearAllModal}
onClose={() => setShowClearAllModal(false)}
onConfirm={handleClearAllPropositions}
campaignTitle={campaign?.title}
propositionCount={propositions.length}
/>
</div>
</div>
);