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
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m14s
This commit is contained in:
100
src/components/collaboration/BaseSessionLiveWrapper.tsx
Normal file
100
src/components/collaboration/BaseSessionLiveWrapper.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useLive, type LiveEvent } from '@/hooks/useLive';
|
||||
import { CollaborationToolbar } from './CollaborationToolbar';
|
||||
import { ShareModal } from './ShareModal';
|
||||
import type { ShareRole } from '@prisma/client';
|
||||
import type { TeamWithMembers, Share } from '@/lib/share-utils';
|
||||
|
||||
export type LiveApiPath = 'sessions' | 'motivators' | 'weather' | 'year-review' | 'weekly-checkin';
|
||||
|
||||
interface ShareModalConfig {
|
||||
title: string;
|
||||
sessionSubtitle: string;
|
||||
helpText: React.ReactNode;
|
||||
}
|
||||
|
||||
interface BaseSessionLiveWrapperConfig {
|
||||
apiPath: LiveApiPath;
|
||||
shareModal: ShareModalConfig;
|
||||
onShareWithEmail: (email: string, role: ShareRole) => Promise<{ success: boolean; error?: string }>;
|
||||
onRemoveShare: (userId: string) => Promise<unknown>;
|
||||
onShareWithTeam?: (teamId: string, role: ShareRole) => Promise<{ success: boolean; error?: string }>;
|
||||
}
|
||||
|
||||
interface BaseSessionLiveWrapperProps {
|
||||
sessionId: string;
|
||||
sessionTitle: string;
|
||||
currentUserId: string;
|
||||
shares: Share[];
|
||||
isOwner: boolean;
|
||||
canEdit: boolean;
|
||||
userTeams?: TeamWithMembers[];
|
||||
children: React.ReactNode;
|
||||
config: BaseSessionLiveWrapperConfig;
|
||||
}
|
||||
|
||||
export function BaseSessionLiveWrapper({
|
||||
sessionId,
|
||||
sessionTitle,
|
||||
currentUserId,
|
||||
shares,
|
||||
isOwner,
|
||||
canEdit,
|
||||
userTeams = [],
|
||||
children,
|
||||
config,
|
||||
}: BaseSessionLiveWrapperProps) {
|
||||
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 } = useLive({
|
||||
sessionId,
|
||||
apiPath: config.apiPath,
|
||||
currentUserId,
|
||||
onEvent: handleEvent,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<CollaborationToolbar
|
||||
isConnected={isConnected}
|
||||
error={error}
|
||||
lastEventUser={lastEventUser}
|
||||
canEdit={canEdit}
|
||||
shares={shares}
|
||||
onShareClick={() => setShareModalOpen(true)}
|
||||
/>
|
||||
|
||||
{/* Content */}
|
||||
<div className={!canEdit ? 'pointer-events-none opacity-90' : ''}>{children}</div>
|
||||
|
||||
{/* Share Modal */}
|
||||
<ShareModal
|
||||
isOpen={shareModalOpen}
|
||||
onClose={() => setShareModalOpen(false)}
|
||||
title={config.shareModal.title}
|
||||
sessionSubtitle={config.shareModal.sessionSubtitle}
|
||||
sessionTitle={sessionTitle}
|
||||
shares={shares}
|
||||
isOwner={isOwner}
|
||||
userTeams={userTeams}
|
||||
currentUserId={currentUserId}
|
||||
onShareWithEmail={config.onShareWithEmail}
|
||||
onShareWithTeam={config.onShareWithTeam}
|
||||
onRemoveShare={config.onRemoveShare}
|
||||
helpText={config.shareModal.helpText}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user