liens publics pour voter pour les participants
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { Campaign, Participant } from '@/types';
|
||||
import { campaignService, participantService } from '@/lib/services';
|
||||
import { Campaign, Participant, ParticipantWithVoteStatus } from '@/types';
|
||||
import { campaignService, participantService, voteService } from '@/lib/services';
|
||||
import AddParticipantModal from '@/components/AddParticipantModal';
|
||||
import EditParticipantModal from '@/components/EditParticipantModal';
|
||||
import DeleteParticipantModal from '@/components/DeleteParticipantModal';
|
||||
@@ -17,12 +17,13 @@ export default function CampaignParticipantsPage() {
|
||||
const campaignId = params.id as string;
|
||||
|
||||
const [campaign, setCampaign] = useState<Campaign | null>(null);
|
||||
const [participants, setParticipants] = useState<Participant[]>([]);
|
||||
const [participants, setParticipants] = useState<ParticipantWithVoteStatus[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [showAddModal, setShowAddModal] = useState(false);
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
const [selectedParticipant, setSelectedParticipant] = useState<Participant | null>(null);
|
||||
const [copiedParticipantId, setCopiedParticipantId] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (campaignId) {
|
||||
@@ -33,13 +34,13 @@ export default function CampaignParticipantsPage() {
|
||||
const loadData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const [campaignData, participantsData] = await Promise.all([
|
||||
const [campaigns, participantsWithVoteStatus] = await Promise.all([
|
||||
campaignService.getAll().then(campaigns => campaigns.find(c => c.id === campaignId)),
|
||||
participantService.getByCampaign(campaignId)
|
||||
voteService.getParticipantVoteStatus(campaignId)
|
||||
]);
|
||||
|
||||
setCampaign(campaignData || null);
|
||||
setParticipants(participantsData);
|
||||
setCampaign(campaigns || null);
|
||||
setParticipants(participantsWithVoteStatus);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du chargement des données:', error);
|
||||
} finally {
|
||||
@@ -181,9 +182,65 @@ export default function CampaignParticipantsPage() {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs text-gray-500">
|
||||
Inscrit le {new Date(participant.created_at).toLocaleDateString('fr-FR')}
|
||||
</p>
|
||||
<div className="flex items-center space-x-4 text-xs text-gray-500">
|
||||
<span>
|
||||
<strong>Inscrit le :</strong> {new Date(participant.created_at).toLocaleDateString('fr-FR')}
|
||||
</span>
|
||||
<span className={`inline-flex items-center px-2 py-1 rounded-full text-xs font-medium ${
|
||||
participant.has_voted
|
||||
? 'bg-green-100 text-green-800'
|
||||
: 'bg-yellow-100 text-yellow-800'
|
||||
}`}>
|
||||
{participant.has_voted ? 'A voté' : 'N\'a pas voté'}
|
||||
</span>
|
||||
{participant.has_voted && participant.total_voted_amount && (
|
||||
<span>
|
||||
<strong>Total voté :</strong> {participant.total_voted_amount}€
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{campaign?.status === 'voting' && (
|
||||
<div className="mt-4 p-3 bg-blue-50 rounded-lg border border-blue-200">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
<h4 className="text-sm font-medium text-blue-900 mb-1">Lien de vote personnel</h4>
|
||||
<div className="flex items-center space-x-2">
|
||||
<input
|
||||
type="text"
|
||||
readOnly
|
||||
value={`${window.location.origin}/campaigns/${campaignId}/vote/${participant.id}`}
|
||||
className="flex-1 text-xs bg-white border border-blue-300 rounded px-2 py-1 text-blue-700 font-mono"
|
||||
/>
|
||||
<button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(`${window.location.origin}/campaigns/${campaignId}/vote/${participant.id}`);
|
||||
setCopiedParticipantId(participant.id);
|
||||
setTimeout(() => setCopiedParticipantId(null), 2000);
|
||||
}}
|
||||
className="inline-flex items-center px-2 py-1 border border-blue-300 rounded text-xs font-medium text-blue-700 bg-white hover:bg-blue-50"
|
||||
title="Copier le lien"
|
||||
>
|
||||
{copiedParticipantId === participant.id ? (
|
||||
<>
|
||||
<svg className="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
Copié !
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 ml-6">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user