Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 1x 5x 5x 5x 5x 5x 5x 5x | /**
* CockpitTab (Epic 14 Phase B — Story 14.B.1; FR7).
*
* The task-driven Cockpit landing — three stacked regions:
* 1. lifecycle spine ("where is this event")
* 2. "Needs your attention" (sorted, only-open cards + +Add task)
* 3. "At a glance" metric tiles (clickable deep-links)
*
* No event-identity block here — identity lives in Details; orientation is the
* persistent header title + the spine (FR7). Replaces the interim Overview mount.
*/
import React from 'react';
import { Stack, Typography } from '@mui/material';
import { useTranslation } from 'react-i18next';
import type { Event, EventDetailUI } from '@/types/event.types';
import { useAuth } from '@/hooks/useAuth';
import { useBreakpoints } from '@/hooks/useBreakpoints';
import { WORKFLOW_RELEVANCE, type WorkflowStateType } from '@/utils/workflow/workflowState';
import { LifecycleSpine } from './LifecycleSpine';
import { AttentionList } from './AttentionList';
import { MetricTiles } from './MetricTiles';
import { useCockpitCards } from './useCockpitCards';
import type { CardTarget } from './cockpitCards';
interface CockpitTabProps {
event: Event | EventDetailUI;
eventCode: string;
/** Deep-link handler from EventPage (tab/sub-view switch or route navigation). */
onNavigate: (target: CardTarget) => void;
}
export const CockpitTab: React.FC<CockpitTabProps> = ({ event, eventCode, onNavigate }) => {
const { t } = useTranslation('events');
const { user } = useAuth();
const { isMobile } = useBreakpoints();
const workflowState = (event as { workflowState?: string }).workflowState ?? '';
const { cards, isLoading, isError, refetch } = useCockpitCards(event, eventCode);
const emphasis = WORKFLOW_RELEVANCE[workflowState as WorkflowStateType]?.cockpitEmphasis;
return (
<Stack spacing={4} data-testid="cockpit-tab">
{/* Region 1 — lifecycle spine */}
<div>
{/* Mobile (Phase G — 14.G.2): the spine collapses to a "Step N/8" bar. */}
<LifecycleSpine workflowState={workflowState} compact={isMobile} />
{emphasis && (
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
{t(`eventPage.cockpit.emphasis.${emphasis}`, '')}
</Typography>
)}
</div>
{/* Region 2 — needs your attention */}
<AttentionList
cards={cards}
isLoading={isLoading}
isError={isError}
onRetry={refetch}
onNavigate={onNavigate}
eventCode={eventCode}
organizerUsername={user?.username ?? ''}
/>
{/* Region 3 — at a glance */}
<div>
<Typography variant="h6" gutterBottom>
{t('eventPage.cockpit.atAGlance.title', 'At a glance')}
</Typography>
<MetricTiles event={event} onNavigate={onNavigate} />
</div>
</Stack>
);
};
export default CockpitTab;
|