feat: add team collaboration sessions for admins, enhancing session management and visibility in the application
This commit is contained in:
@@ -28,6 +28,7 @@ import {
|
||||
|
||||
const TYPE_TABS = [
|
||||
{ value: 'all' as const, icon: '📋', label: 'Tous' },
|
||||
{ value: 'team' as const, icon: '🏢', label: 'Équipe' },
|
||||
...WORKSHOPS.map((w) => ({ value: w.id, icon: w.icon, label: w.labelShort })),
|
||||
];
|
||||
|
||||
@@ -131,6 +132,7 @@ interface WorkshopTabsProps {
|
||||
yearReviewSessions: YearReviewSession[];
|
||||
weeklyCheckInSessions: WeeklyCheckInSession[];
|
||||
weatherSessions: WeatherSession[];
|
||||
teamCollabSessions?: (AnySession & { isTeamCollab?: true })[];
|
||||
}
|
||||
|
||||
// Helper to get resolved collaborator from any session
|
||||
@@ -197,6 +199,7 @@ export function WorkshopTabs({
|
||||
yearReviewSessions,
|
||||
weeklyCheckInSessions,
|
||||
weatherSessions,
|
||||
teamCollabSessions = [],
|
||||
}: WorkshopTabsProps) {
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
@@ -219,7 +222,7 @@ export function WorkshopTabs({
|
||||
router.push(`/sessions${params.toString() ? `?${params.toString()}` : ''}`);
|
||||
};
|
||||
|
||||
// Combine and sort all sessions
|
||||
// Combine and sort all sessions (exclude team collab from main list - they're shown separately)
|
||||
const allSessions: AnySession[] = [
|
||||
...swotSessions,
|
||||
...motivatorSessions,
|
||||
@@ -232,7 +235,9 @@ export function WorkshopTabs({
|
||||
const filteredSessions =
|
||||
activeTab === 'all' || activeTab === 'byPerson'
|
||||
? allSessions
|
||||
: activeTab === 'swot'
|
||||
: activeTab === 'team'
|
||||
? teamCollabSessions
|
||||
: activeTab === 'swot'
|
||||
? swotSessions
|
||||
: activeTab === 'motivators'
|
||||
? motivatorSessions
|
||||
@@ -242,9 +247,11 @@ export function WorkshopTabs({
|
||||
? weeklyCheckInSessions
|
||||
: weatherSessions;
|
||||
|
||||
// Separate by ownership
|
||||
// Separate by ownership (for non-team tab: owned, shared, teamCollab)
|
||||
const ownedSessions = filteredSessions.filter((s) => s.isOwner);
|
||||
const sharedSessions = filteredSessions.filter((s) => !s.isOwner);
|
||||
const sharedSessions = filteredSessions.filter((s) => !s.isOwner && !(s as AnySession & { isTeamCollab?: boolean }).isTeamCollab);
|
||||
const teamCollabFiltered =
|
||||
activeTab === 'all' ? teamCollabSessions : activeTab === 'team' ? teamCollabSessions : [];
|
||||
|
||||
// Group by person (all sessions - owned and shared)
|
||||
const sessionsByPerson = groupByPerson(allSessions);
|
||||
@@ -270,6 +277,15 @@ export function WorkshopTabs({
|
||||
label="Par personne"
|
||||
count={sessionsByPerson.size}
|
||||
/>
|
||||
{teamCollabSessions.length > 0 && (
|
||||
<TabButton
|
||||
active={activeTab === 'team'}
|
||||
onClick={() => setActiveTab('team')}
|
||||
icon="🏢"
|
||||
label="Équipe"
|
||||
count={teamCollabSessions.length}
|
||||
/>
|
||||
)}
|
||||
<TypeFilterDropdown
|
||||
activeTab={activeTab}
|
||||
setActiveTab={setActiveTab}
|
||||
@@ -281,6 +297,7 @@ export function WorkshopTabs({
|
||||
'year-review': yearReviewSessions.length,
|
||||
'weekly-checkin': weeklyCheckInSessions.length,
|
||||
weather: weatherSessions.length,
|
||||
team: teamCollabSessions.length,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -312,6 +329,28 @@ export function WorkshopTabs({
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
) : activeTab === 'team' ? (
|
||||
teamCollabSessions.length === 0 ? (
|
||||
<div className="text-center py-12 text-muted">
|
||||
Aucun atelier de vos collaborateurs d'équipe (non partagés avec vous)
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-8">
|
||||
<section>
|
||||
<h2 className="text-lg font-semibold text-muted mb-4">
|
||||
🏢 Ateliers de l'équipe – non partagés ({teamCollabSessions.length})
|
||||
</h2>
|
||||
<p className="text-sm text-muted mb-4">
|
||||
En tant qu'admin d'équipe, vous voyez les ateliers de vos collaborateurs qui ne vous sont pas encore partagés.
|
||||
</p>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{teamCollabSessions.map((s) => (
|
||||
<SessionCard key={s.id} session={s} isTeamCollab />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
) : filteredSessions.length === 0 ? (
|
||||
<div className="text-center py-12 text-muted">Aucun atelier de ce type pour le moment</div>
|
||||
) : (
|
||||
@@ -343,6 +382,20 @@ export function WorkshopTabs({
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* Team collab sessions (non-shared) - grayed out, admin view only */}
|
||||
{activeTab === 'all' && teamCollabFiltered.length > 0 && (
|
||||
<section>
|
||||
<h2 className="text-lg font-semibold text-muted mb-4">
|
||||
🏢 Équipe – non partagés ({teamCollabFiltered.length})
|
||||
</h2>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{teamCollabFiltered.map((s) => (
|
||||
<SessionCard key={s.id} session={s} isTeamCollab />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -470,7 +523,7 @@ function TabButton({
|
||||
);
|
||||
}
|
||||
|
||||
function SessionCard({ session }: { session: AnySession }) {
|
||||
function SessionCard({ session, isTeamCollab = false }: { session: AnySession; isTeamCollab?: boolean }) {
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
const [isPending, startTransition] = useTransition();
|
||||
@@ -562,11 +615,8 @@ function SessionCard({ session }: { session: AnySession }) {
|
||||
|
||||
const editParticipantLabel = workshop.participantLabel;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative group">
|
||||
<Link href={href}>
|
||||
<Card hover className="h-full p-4 relative overflow-hidden">
|
||||
const cardContent = (
|
||||
<Card hover={!isTeamCollab} className={`h-full p-4 relative overflow-hidden ${isTeamCollab ? 'opacity-60' : ''}`}>
|
||||
{/* Accent bar */}
|
||||
<div
|
||||
className="absolute top-0 left-0 right-0 h-1"
|
||||
@@ -677,7 +727,21 @@ function SessionCard({ session }: { session: AnySession }) {
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</Link>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative group">
|
||||
{isTeamCollab ? (
|
||||
<div
|
||||
className="cursor-default"
|
||||
title="Atelier non partagé avec vous – visible en tant qu'admin d'équipe"
|
||||
>
|
||||
{cardContent}
|
||||
</div>
|
||||
) : (
|
||||
<Link href={href}>{cardContent}</Link>
|
||||
)}
|
||||
|
||||
{/* Action buttons - only for owner */}
|
||||
{session.isOwner && (
|
||||
|
||||
Reference in New Issue
Block a user