feat: refactor session components to utilize BaseSessionLiveWrapper, streamlining sharing functionality and reducing code duplication across various session types
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m14s

This commit is contained in:
Julien Froidefond
2026-02-18 08:39:15 +01:00
parent 35228441e3
commit 739b0bf87d
18 changed files with 381 additions and 795 deletions

View File

@@ -1,27 +1,8 @@
'use client';
import { useState, useCallback } from 'react';
import { useSessionLive, type LiveEvent } from '@/hooks/useSessionLive';
import { LiveIndicator } from './LiveIndicator';
import { ShareModal } from './ShareModal';
import { BaseSessionLiveWrapper } from './BaseSessionLiveWrapper';
import { shareSessionAction, removeShareAction } from '@/actions/share';
import { Button } from '@/components/ui/Button';
import { Avatar } from '@/components/ui/Avatar';
import type { ShareRole } from '@prisma/client';
import type { TeamWithMembers } from '@/lib/share-utils';
interface ShareUser {
id: string;
name: string | null;
email: string;
}
interface Share {
id: string;
role: ShareRole;
user: ShareUser;
createdAt: Date;
}
import type { TeamWithMembers, Share } from '@/lib/share-utils';
interface SessionLiveWrapperProps {
sessionId: string;
@@ -44,105 +25,33 @@ export function SessionLiveWrapper({
userTeams = [],
children,
}: SessionLiveWrapperProps) {
const [shareModalOpen, setShareModalOpen] = useState(false);
const [lastEventUser, setLastEventUser] = useState<string | null>(null);
const handleEvent = useCallback((event: LiveEvent) => {
// Show who made the last change
if (event.user?.name || event.user?.email) {
setLastEventUser(event.user.name || event.user.email);
// Clear after 3 seconds
setTimeout(() => setLastEventUser(null), 3000);
}
}, []);
const { isConnected, error } = useSessionLive({
sessionId,
currentUserId,
onEvent: handleEvent,
});
return (
<>
{/* Header toolbar */}
<div className="mb-4 flex items-center justify-between rounded-lg border border-border bg-card p-3">
<div className="flex items-center gap-4">
<LiveIndicator isConnected={isConnected} error={error} />
{lastEventUser && (
<div className="flex items-center gap-2 text-sm text-muted animate-pulse">
<span></span>
<span>{lastEventUser} édite...</span>
</div>
)}
{!canEdit && (
<div className="flex items-center gap-2 rounded-full bg-yellow/10 px-3 py-1.5 text-sm text-yellow">
<span>👁</span>
<span>Mode lecture</span>
</div>
)}
</div>
<div className="flex items-center gap-2">
{/* Collaborators avatars */}
{shares.length > 0 && (
<div className="flex -space-x-2">
{shares.slice(0, 3).map((share) => (
<Avatar
key={share.id}
email={share.user.email}
name={share.user.name}
size={32}
className="border-2 border-card"
/>
))}
{shares.length > 3 && (
<div className="flex h-8 w-8 items-center justify-center rounded-full border-2 border-card bg-muted/20 text-xs font-medium text-muted">
+{shares.length - 3}
</div>
)}
</div>
)}
<Button variant="outline" size="sm" onClick={() => setShareModalOpen(true)}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="mr-2 h-4 w-4"
>
<path d="M13 4.5a2.5 2.5 0 11.702 1.737L6.97 9.604a2.518 2.518 0 010 .792l6.733 3.367a2.5 2.5 0 11-.671 1.341l-6.733-3.367a2.5 2.5 0 110-3.475l6.733-3.366A2.52 2.52 0 0113 4.5z" />
</svg>
Partager
</Button>
</div>
</div>
{/* Content */}
<div className={!canEdit ? 'pointer-events-none opacity-90' : ''}>{children}</div>
{/* Share Modal */}
<ShareModal
isOpen={shareModalOpen}
onClose={() => setShareModalOpen(false)}
title="Partager la session"
sessionSubtitle="Session"
sessionTitle={sessionTitle}
shares={shares}
isOwner={isOwner}
userTeams={userTeams}
currentUserId={currentUserId}
onShareWithEmail={(email, role) => shareSessionAction(sessionId, email, role)}
onRemoveShare={(userId) => removeShareAction(sessionId, userId)}
helpText={
<>
<strong>Éditeur</strong> : peut modifier les items et actions
<br />
<strong>Lecteur</strong> : peut uniquement consulter
</>
}
/>
</>
<BaseSessionLiveWrapper
sessionId={sessionId}
sessionTitle={sessionTitle}
currentUserId={currentUserId}
shares={shares}
isOwner={isOwner}
canEdit={canEdit}
userTeams={userTeams}
config={{
apiPath: 'sessions',
shareModal: {
title: 'Partager la session',
sessionSubtitle: 'Session',
helpText: (
<>
<strong>Éditeur</strong> : peut modifier les items et actions
<br />
<strong>Lecteur</strong> : peut uniquement consulter
</>
),
},
onShareWithEmail: (email, role) => shareSessionAction(sessionId, email, role),
onRemoveShare: (userId) => removeShareAction(sessionId, userId),
}}
>
{children}
</BaseSessionLiveWrapper>
);
}