feat: implement session deletion functionality with confirmation modal in WorkshopTabs component

This commit is contained in:
Julien Froidefond
2025-11-28 10:44:01 +01:00
parent 4c63945505
commit ac079ed8b2
3 changed files with 176 additions and 82 deletions

BIN
dev.db

Binary file not shown.

View File

@@ -70,3 +70,24 @@ export async function updateSessionCollaborator(sessionId: string, collaborator:
} }
} }
export async function deleteSwotSession(sessionId: string) {
const session = await auth();
if (!session?.user?.id) {
return { success: false, error: 'Non autorisé' };
}
try {
const result = await sessionsService.deleteSession(sessionId, session.user.id);
if (result.count === 0) {
return { success: false, error: 'Session non trouvée ou non autorisé' };
}
revalidatePath('/sessions');
return { success: true };
} catch (error) {
console.error('Error deleting session:', error);
return { success: false, error: 'Erreur lors de la suppression' };
}
}

View File

@@ -1,8 +1,10 @@
'use client'; 'use client';
import { useState } from 'react'; import { useState, useTransition } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import { Card, Badge } from '@/components/ui'; import { Card, Badge, Button, Modal, ModalFooter } from '@/components/ui';
import { deleteSwotSession } from '@/actions/session';
import { deleteMotivatorSession } from '@/actions/moving-motivators';
type WorkshopType = 'all' | 'swot' | 'motivators'; type WorkshopType = 'all' | 'swot' | 'motivators';
@@ -172,6 +174,9 @@ function TabButton({
} }
function SessionCard({ session }: { session: AnySession }) { function SessionCard({ session }: { session: AnySession }) {
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [isPending, startTransition] = useTransition();
const isSwot = session.workshopType === 'swot'; const isSwot = session.workshopType === 'swot';
const href = isSwot ? `/sessions/${session.id}` : `/motivators/${session.id}`; const href = isSwot ? `/sessions/${session.id}` : `/motivators/${session.id}`;
const icon = isSwot ? '📊' : '🎯'; const icon = isSwot ? '📊' : '🎯';
@@ -180,7 +185,23 @@ function SessionCard({ session }: { session: AnySession }) {
: (session as MotivatorSession).participant; : (session as MotivatorSession).participant;
const accentColor = isSwot ? '#06b6d4' : '#8b5cf6'; const accentColor = isSwot ? '#06b6d4' : '#8b5cf6';
const handleDelete = () => {
startTransition(async () => {
const result = isSwot
? await deleteSwotSession(session.id)
: await deleteMotivatorSession(session.id);
if (result.success) {
setShowDeleteModal(false);
} else {
console.error('Error deleting session:', result.error);
}
});
};
return ( return (
<>
<div className="relative group">
<Link href={href}> <Link href={href}>
<Card hover className="h-full p-4 relative overflow-hidden"> <Card hover className="h-full p-4 relative overflow-hidden">
{/* Accent bar */} {/* Accent bar */}
@@ -267,6 +288,58 @@ function SessionCard({ session }: { session: AnySession }) {
)} )}
</Card> </Card>
</Link> </Link>
{/* Delete button - only for owner */}
{session.isOwner && (
<button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setShowDeleteModal(true);
}}
className="absolute top-3 right-3 p-1.5 rounded-lg opacity-0 group-hover:opacity-100 transition-opacity bg-destructive/10 text-destructive hover:bg-destructive/20"
title="Supprimer"
>
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
)}
</div>
{/* Delete confirmation modal */}
<Modal
isOpen={showDeleteModal}
onClose={() => setShowDeleteModal(false)}
title="Supprimer l'atelier"
size="sm"
>
<div className="space-y-4">
<p className="text-muted">
Êtes-vous sûr de vouloir supprimer l&apos;atelier <strong className="text-foreground">&quot;{session.title}&quot;</strong> ?
</p>
<p className="text-sm text-destructive">
Cette action est irréversible. Toutes les données seront perdues.
</p>
<ModalFooter>
<Button
variant="ghost"
onClick={() => setShowDeleteModal(false)}
disabled={isPending}
>
Annuler
</Button>
<Button
variant="destructive"
onClick={handleDelete}
disabled={isPending}
>
{isPending ? 'Suppression...' : 'Supprimer'}
</Button>
</ModalFooter>
</div>
</Modal>
</>
); );
} }