feat: implement Moving Motivators feature with session management, real-time event handling, and UI components for enhanced user experience

This commit is contained in:
Julien Froidefond
2025-11-28 08:40:39 +01:00
parent a5c17e23f6
commit 448cf61e66
26 changed files with 3191 additions and 183 deletions

View File

@@ -0,0 +1,218 @@
'use server';
import { revalidatePath } from 'next/cache';
import { auth } from '@/lib/auth';
import * as motivatorsService from '@/services/moving-motivators';
// ============================================
// Session Actions
// ============================================
export async function createMotivatorSession(data: { title: string; participant: string }) {
const session = await auth();
if (!session?.user?.id) {
return { success: false, error: 'Non autorisé' };
}
try {
const motivatorSession = await motivatorsService.createMotivatorSession(
session.user.id,
data
);
revalidatePath('/motivators');
return { success: true, data: motivatorSession };
} catch (error) {
console.error('Error creating motivator session:', error);
return { success: false, error: 'Erreur lors de la création' };
}
}
export async function updateMotivatorSession(
sessionId: string,
data: { title?: string; participant?: string }
) {
const authSession = await auth();
if (!authSession?.user?.id) {
return { success: false, error: 'Non autorisé' };
}
try {
await motivatorsService.updateMotivatorSession(sessionId, authSession.user.id, data);
// Emit event for real-time sync
await motivatorsService.createMotivatorSessionEvent(
sessionId,
authSession.user.id,
'SESSION_UPDATED',
data
);
revalidatePath(`/motivators/${sessionId}`);
revalidatePath('/motivators');
return { success: true };
} catch (error) {
console.error('Error updating motivator session:', error);
return { success: false, error: 'Erreur lors de la mise à jour' };
}
}
export async function deleteMotivatorSession(sessionId: string) {
const authSession = await auth();
if (!authSession?.user?.id) {
return { success: false, error: 'Non autorisé' };
}
try {
await motivatorsService.deleteMotivatorSession(sessionId, authSession.user.id);
revalidatePath('/motivators');
return { success: true };
} catch (error) {
console.error('Error deleting motivator session:', error);
return { success: false, error: 'Erreur lors de la suppression' };
}
}
// ============================================
// Card Actions
// ============================================
export async function updateMotivatorCard(
cardId: string,
sessionId: string,
data: { orderIndex?: number; influence?: number }
) {
const authSession = await auth();
if (!authSession?.user?.id) {
return { success: false, error: 'Non autorisé' };
}
// Check edit permission
const canEdit = await motivatorsService.canEditMotivatorSession(
sessionId,
authSession.user.id
);
if (!canEdit) {
return { success: false, error: 'Permission refusée' };
}
try {
const card = await motivatorsService.updateMotivatorCard(cardId, data);
// Emit event for real-time sync
if (data.influence !== undefined) {
await motivatorsService.createMotivatorSessionEvent(
sessionId,
authSession.user.id,
'CARD_INFLUENCE_CHANGED',
{ cardId, influence: data.influence, type: card.type }
);
} else if (data.orderIndex !== undefined) {
await motivatorsService.createMotivatorSessionEvent(
sessionId,
authSession.user.id,
'CARD_MOVED',
{ cardId, orderIndex: data.orderIndex, type: card.type }
);
}
revalidatePath(`/motivators/${sessionId}`);
return { success: true, data: card };
} catch (error) {
console.error('Error updating motivator card:', error);
return { success: false, error: 'Erreur lors de la mise à jour' };
}
}
export async function reorderMotivatorCards(sessionId: string, cardIds: string[]) {
const authSession = await auth();
if (!authSession?.user?.id) {
return { success: false, error: 'Non autorisé' };
}
// Check edit permission
const canEdit = await motivatorsService.canEditMotivatorSession(
sessionId,
authSession.user.id
);
if (!canEdit) {
return { success: false, error: 'Permission refusée' };
}
try {
await motivatorsService.reorderMotivatorCards(sessionId, cardIds);
// Emit event for real-time sync
await motivatorsService.createMotivatorSessionEvent(
sessionId,
authSession.user.id,
'CARDS_REORDERED',
{ cardIds }
);
revalidatePath(`/motivators/${sessionId}`);
return { success: true };
} catch (error) {
console.error('Error reordering motivator cards:', error);
return { success: false, error: 'Erreur lors du réordonnancement' };
}
}
export async function updateCardInfluence(
cardId: string,
sessionId: string,
influence: number
) {
return updateMotivatorCard(cardId, sessionId, { influence });
}
// ============================================
// Sharing Actions
// ============================================
export async function shareMotivatorSession(
sessionId: string,
targetEmail: string,
role: 'VIEWER' | 'EDITOR' = 'EDITOR'
) {
const authSession = await auth();
if (!authSession?.user?.id) {
return { success: false, error: 'Non autorisé' };
}
try {
const share = await motivatorsService.shareMotivatorSession(
sessionId,
authSession.user.id,
targetEmail,
role
);
revalidatePath(`/motivators/${sessionId}`);
return { success: true, data: share };
} catch (error) {
console.error('Error sharing motivator session:', error);
const message =
error instanceof Error ? error.message : 'Erreur lors du partage';
return { success: false, error: message };
}
}
export async function removeMotivatorShare(sessionId: string, shareUserId: string) {
const authSession = await auth();
if (!authSession?.user?.id) {
return { success: false, error: 'Non autorisé' };
}
try {
await motivatorsService.removeMotivatorShare(
sessionId,
authSession.user.id,
shareUserId
);
revalidatePath(`/motivators/${sessionId}`);
return { success: true };
} catch (error) {
console.error('Error removing motivator share:', error);
return { success: false, error: 'Erreur lors de la suppression du partage' };
}
}