All files / src/components/organizer/PartnerManagement PartnerTabNavigation.tsx

96.29% Statements 26/27
83.33% Branches 10/12
100% Functions 5/5
96.29% Lines 26/27

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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94                        5x         59x 59x 59x   59x                           59x   63x       59x 3x     59x 8x   8x   3x 3x 3x   2x 2x 2x   2x 2x 2x   1x 1x 1x           59x                       386x                      
import React from 'react';
import { Tabs, Tab, Box, useTheme, useMediaQuery } from '@mui/material';
import { useTranslation } from 'react-i18next';
 
type UserRole = 'ORGANIZER' | 'PARTNER' | 'SPEAKER' | 'ATTENDEE';
 
interface PartnerTabNavigationProps {
  activeTab: number;
  onTabChange: (tabIndex: number) => void;
  role?: UserRole;
}
 
export const PartnerTabNavigation: React.FC<PartnerTabNavigationProps> = ({
  activeTab,
  onTabChange,
  role,
}) => {
  const { t } = useTranslation('partners');
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm')); // <640px
 
  const allTabs = [
    { key: 'overview', label: t('common:labels.overview') },
    { key: 'contacts', label: t('detail.tabs.contacts') },
    { key: 'meetings', label: t('detail.tabs.meetings') },
    { key: 'analytics', label: t('common:navigation.analytics') },
    { key: 'notes', label: t('common:labels.notes') },
    { key: 'topics', label: t('common:labels.topics') },
    { key: 'settings', label: t('detail.tabs.settings') },
  ];
 
  // Story 8.0: Settings tab hidden for PARTNER role
  // Story 8.4: Notes tab also hidden for PARTNER (organizer-internal notes)
  // Topics tab: hidden for PARTNER — organizer-only meeting workflow
  const visibleTabs =
    role === 'PARTNER'
      ? allTabs.filter(
          (tab) => tab.key !== 'settings' && tab.key !== 'notes' && tab.key !== 'topics'
        )
      : allTabs;
 
  const handleChange = (_event: React.SyntheticEvent, newValue: number) => {
    onTabChange(newValue);
  };
 
  const handleKeyDown = (event: React.KeyboardEvent) => {
    const totalTabs = visibleTabs.length;
 
    switch (event.key) {
      case 'ArrowRight':
        event.preventDefault();
        onTabChange((activeTab + 1) % totalTabs);
        break;
      case 'ArrowLeft':
        event.preventDefault();
        onTabChange((activeTab - 1 + totalTabs) % totalTabs);
        break;
      case 'Home':
        event.preventDefault();
        onTabChange(0);
        break;
      case 'End':
        event.preventDefault();
        onTabChange(totalTabs - 1);
        break;
      default:
        break;
    }
  };
 
  return (
    <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
      <Tabs
        value={activeTab}
        onChange={handleChange}
        onKeyDown={handleKeyDown}
        aria-label={t('detail.tabs.partnerDetailTabs')}
        variant="scrollable"
        scrollButtons="auto"
        orientation={isMobile ? 'vertical' : 'horizontal'}
      >
        {visibleTabs.map((tab, index) => (
          <Tab
            key={tab.key}
            label={tab.label}
            id={`partner-tab-${index}`}
            aria-controls={`partner-tabpanel-${index}`}
          />
        ))}
      </Tabs>
    </Box>
  );
};