refactor: add SessionPageHeader and apply to all 6 session detail pages
- Create SessionPageHeader component (breadcrumb + editable title + collaborator + badges + date) - Embed UPDATE_FN map internally, keyed by workshopType — no prop drilling - Replace duplicated header blocks in sessions, motivators, year-review, weather, weekly-checkin, gif-mood Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
95
src/components/ui/SessionPageHeader.tsx
Normal file
95
src/components/ui/SessionPageHeader.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { ReactNode } from 'react';
|
||||
import { getWorkshop, getSessionsTabUrl, WorkshopTypeId } from '@/lib/workshops';
|
||||
import { Badge } from './Badge';
|
||||
import { EditableTitle } from './EditableTitle';
|
||||
import { CollaboratorDisplay } from './CollaboratorDisplay';
|
||||
import type { ResolvedCollaborator } from '@/services/auth';
|
||||
import { updateSessionTitle } from '@/actions/session';
|
||||
import { updateMotivatorSession } from '@/actions/moving-motivators';
|
||||
import { updateYearReviewSession } from '@/actions/year-review';
|
||||
import { updateWeatherSession } from '@/actions/weather';
|
||||
import { updateWeeklyCheckInSession } from '@/actions/weekly-checkin';
|
||||
import { updateGifMoodSession } from '@/actions/gif-mood';
|
||||
|
||||
type UpdateFn = (id: string, title: string) => Promise<{ success: boolean; error?: string }>;
|
||||
|
||||
const UPDATE_FN: Record<WorkshopTypeId, UpdateFn> = {
|
||||
'swot': updateSessionTitle,
|
||||
'motivators': (id, title) => updateMotivatorSession(id, { title }),
|
||||
'year-review': (id, title) => updateYearReviewSession(id, { title }),
|
||||
'weekly-checkin': (id, title) => updateWeeklyCheckInSession(id, { title }),
|
||||
'weather': (id, title) => updateWeatherSession(id, { title }),
|
||||
'gif-mood': (id, title) => updateGifMoodSession(id, { title }),
|
||||
};
|
||||
|
||||
interface SessionPageHeaderProps {
|
||||
workshopType: WorkshopTypeId;
|
||||
sessionId: string;
|
||||
sessionTitle: string;
|
||||
isOwner: boolean;
|
||||
canEdit: boolean;
|
||||
ownerUser: { name: string | null; email: string };
|
||||
date: Date | string;
|
||||
collaborator?: ResolvedCollaborator | null;
|
||||
badges?: ReactNode;
|
||||
}
|
||||
|
||||
export function SessionPageHeader({
|
||||
workshopType,
|
||||
sessionId,
|
||||
sessionTitle,
|
||||
isOwner,
|
||||
canEdit,
|
||||
ownerUser,
|
||||
date,
|
||||
collaborator,
|
||||
badges,
|
||||
}: SessionPageHeaderProps) {
|
||||
const workshop = getWorkshop(workshopType);
|
||||
|
||||
return (
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center gap-2 text-sm text-muted mb-2">
|
||||
<Link href={getSessionsTabUrl(workshopType)} className="hover:text-foreground">
|
||||
{workshop.labelShort}
|
||||
</Link>
|
||||
<span>/</span>
|
||||
<span className="text-foreground">{sessionTitle}</span>
|
||||
{!isOwner && (
|
||||
<Badge variant="accent" className="ml-2">
|
||||
Partagé par {ownerUser.name || ownerUser.email}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<EditableTitle
|
||||
sessionId={sessionId}
|
||||
initialTitle={sessionTitle}
|
||||
canEdit={canEdit}
|
||||
onUpdate={UPDATE_FN[workshopType]}
|
||||
/>
|
||||
{collaborator && (
|
||||
<div className="mt-2">
|
||||
<CollaboratorDisplay collaborator={collaborator} size="lg" showEmail />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
{badges}
|
||||
<span className="text-sm text-muted">
|
||||
{new Date(date).toLocaleDateString('fr-FR', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -13,6 +13,7 @@ export {
|
||||
EditableGifMoodTitle,
|
||||
} from './EditableTitles';
|
||||
export { PageHeader } from './PageHeader';
|
||||
export { SessionPageHeader } from './SessionPageHeader';
|
||||
export { Input } from './Input';
|
||||
export { ParticipantInput } from './ParticipantInput';
|
||||
export { Modal, ModalFooter } from './Modal';
|
||||
|
||||
Reference in New Issue
Block a user